diff --git a/list.txt b/list.txt index 11e3e0a..e8dfa15 100644 --- a/list.txt +++ b/list.txt @@ -5,4 +5,11 @@ src\main\webapp\WEB-INF\jsp\sgis\com\board\boardList.jsp src\main\resources\egovframework\mapper\sgis\board\PostMapper.xml src\main\webapp\WEB-INF\jsp\sgis\com\board\boardView.jsp src\main\webapp\WEB-INF\jsp\sgis\com\board\boardWrite.jsp -src\main\resources\egovframework\mapper\sgis\board\MemberMapper.xml \ No newline at end of file +src\main\resources\egovframework\mapper\sgis\board\MemberMapper.xml +src\main\webapp\com\js\main.map.js +src\main\webapp\WEB-INF\jsp\sgis\map\mapMain.jsp +src\main\webapp\WEB-INF\jsp\tiles\attribute\app.submenu.jsp +src\main\webapp\WEB-INF\jsp\sgis\map\mapInformation\sichudanNew.jsp +src\main\webapp\com\css\cross-section.css +src\main\webapp\com\js\cross-section.js +src\main\resources\egovframework\mapper\sgis\map\MapMainMapper.xml \ No newline at end of file diff --git a/src/main/java/sgis/map/mapper/MapMainMapper.java b/src/main/java/sgis/map/mapper/MapMainMapper.java index ba47585..97740d5 100644 --- a/src/main/java/sgis/map/mapper/MapMainMapper.java +++ b/src/main/java/sgis/map/mapper/MapMainMapper.java @@ -2,13 +2,51 @@ package sgis.map.mapper; import java.util.HashMap; import java.util.List; +import java.util.Map; import egovframework.rte.psl.dataaccess.mapper.Mapper; import egovframework.rte.psl.dataaccess.util.EgovMap; -@Mapper("MapMainMapper") +@Mapper("mapMainMapper") public interface MapMainMapper { EgovMap selectMapInfoList(HashMap params) throws Exception; + EgovMap selectHoleCount(Map params) throws Exception; + + List selectHoleList(Map params) throws Exception; + + List selectItems(Map params) throws Exception; + + List selectDistrict() throws Exception; + + List selectGrid1(Map params) throws Exception; + + List selectDistrictSgg(Map params) throws Exception; + + List selectOldItems(Map params) throws Exception; + + List get3dSido(Map params) throws Exception; + + List get3dGugun(Map params) throws Exception; + + List get3dDong(Map params) throws Exception; + + List get3dDetail(Map params) throws Exception; + + EgovMap getGeneralData(Map params) throws Exception; + + List getLinkLayerData(Map params) throws Exception; + + List getSPTData(Map params) throws Exception; + + List getSampleData(Map params) throws Exception; + + EgovMap selectInfoLastPage(Map params) throws Exception; + + List selectInfoItems(Map params) throws Exception; + + EgovMap selectWebDownloadLog(Map params) throws Exception; // dhlee 사용자별 다운로드 요청한 개수를 얻어온다. + + List selectProjectList(Map params) throws Exception; } diff --git a/src/main/java/sgis/map/service/MapMainService.java b/src/main/java/sgis/map/service/MapMainService.java index 65ad4d0..4b1df9e 100644 --- a/src/main/java/sgis/map/service/MapMainService.java +++ b/src/main/java/sgis/map/service/MapMainService.java @@ -2,6 +2,7 @@ package sgis.map.service; import java.util.HashMap; import java.util.List; +import java.util.Map; import egovframework.rte.psl.dataaccess.util.EgovMap; import sgis.map.vo.MapInfoVO; @@ -10,4 +11,43 @@ public interface MapMainService { EgovMap selectMapInfoList(HashMap params) throws Exception; + + EgovMap selectHoleCount(Map params) throws Exception; + + List selectHoleList(Map params) throws Exception; + + List selectItems(Map params) throws Exception; + + List selectDistrict() throws Exception; + + List selectGrid1(Map params) throws Exception; + + List selectDistrictSgg(Map params) throws Exception; + + List selectOldItems(Map params) throws Exception; + + List get3dSido(Map params) throws Exception; + + List get3dGugun(Map params) throws Exception; + + List get3dDong(Map params) throws Exception; + + List get3dDetail(Map params) throws Exception; + + EgovMap getGeneralData(Map params) throws Exception; + + List getLinkLayerData(Map params) throws Exception; + + List getSPTData(Map params) throws Exception; + + List getSampleData(Map params) throws Exception; + + EgovMap selectInfoLastPage(Map params) throws Exception; + + List selectInfoItems(Map params) throws Exception; + + EgovMap selectWebDownloadLog(Map params) throws Exception; // dhlee 사용자별 다운로드 요청한 개수를 얻어온다. + + List selectProjectList(Map params) throws Exception; // dhlee + } diff --git a/src/main/java/sgis/map/service/impl/MapMainServiceImpl.java b/src/main/java/sgis/map/service/impl/MapMainServiceImpl.java index 1789d7d..e7a7191 100644 --- a/src/main/java/sgis/map/service/impl/MapMainServiceImpl.java +++ b/src/main/java/sgis/map/service/impl/MapMainServiceImpl.java @@ -2,6 +2,7 @@ package sgis.map.service.impl; import java.util.HashMap; import java.util.List; +import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -14,12 +15,106 @@ import sgis.map.service.MapMainService; public class MapMainServiceImpl implements MapMainService { @Autowired - private MapMainMapper MapMainMapper; + private MapMainMapper mapMainMapper; @Override public EgovMap selectMapInfoList(HashMap params) throws Exception { // TODO Auto-generated method stub - return MapMainMapper.selectMapInfoList(params); + return mapMainMapper.selectMapInfoList(params); } + @Override + public EgovMap selectHoleCount(Map params) throws Exception { + return mapMainMapper.selectHoleCount(params); + } + + @Override + public List selectHoleList(Map params) throws Exception { + return mapMainMapper.selectHoleList(params); + } + + @Override + public List selectItems(Map params) throws Exception { + return mapMainMapper.selectItems(params); + } + + @Override + public List selectDistrict() throws Exception { + return mapMainMapper.selectDistrict(); + } + + @Override + public List selectGrid1(Map params) throws Exception { + return mapMainMapper.selectGrid1(params); + } + + @Override + public List selectDistrictSgg(Map params) throws Exception { + return mapMainMapper.selectDistrictSgg(params); + } + + @Override + public List selectOldItems(Map params) throws Exception { + return mapMainMapper.selectOldItems(params); + } + + @Override + public List get3dSido(Map params) throws Exception { + return mapMainMapper.get3dSido(params); + } + + @Override + public List get3dGugun(Map params) throws Exception { + return mapMainMapper.get3dGugun(params); + } + + @Override + public List get3dDong(Map params) throws Exception { + return mapMainMapper.get3dDong(params); + } + + @Override + public List get3dDetail(Map params) throws Exception { + return mapMainMapper.get3dDetail(params); + } + + @Override + public EgovMap getGeneralData(Map params) throws Exception { + return mapMainMapper.getGeneralData(params); + } + + @Override + public List getLinkLayerData(Map params) throws Exception { + return mapMainMapper.getLinkLayerData(params); + } + + @Override + public List getSPTData(Map params) throws Exception { + return mapMainMapper.getSPTData(params); + } + + @Override + public List getSampleData(Map params) throws Exception { + return mapMainMapper.getSampleData(params); + } + + @Override + public EgovMap selectInfoLastPage(Map params) throws Exception { + return mapMainMapper.selectInfoLastPage(params); + } + + @Override + public List selectInfoItems(Map params) throws Exception { + return mapMainMapper.selectInfoItems(params); + } + + @Override + public EgovMap selectWebDownloadLog(Map params) throws Exception { + return mapMainMapper.selectWebDownloadLog(params); + } + + @Override + public List selectProjectList(Map params) throws Exception { + return mapMainMapper.selectProjectList(params); + } } diff --git a/src/main/java/sgis/map/web/MapMainController.java b/src/main/java/sgis/map/web/MapMainController.java index 1dbf97a..b9e8472 100644 --- a/src/main/java/sgis/map/web/MapMainController.java +++ b/src/main/java/sgis/map/web/MapMainController.java @@ -5,18 +5,21 @@ import java.io.File; import java.io.InputStreamReader; import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseBody; // Add this import import egovframework.rte.psl.dataaccess.util.EgovMap; import sgis.app.service.AppInstrumentService; @@ -28,6 +31,7 @@ import sgis.map.service.AppPredictService; import sgis.map.service.MapMainService; import sgis.map.vo.MapInfoVO; + /** * @FileName : MapMainController.java * @Date : 2022. 05. 10 @@ -38,7 +42,7 @@ import sgis.map.vo.MapInfoVO; public class MapMainController extends BaseController { @Resource(name ="MapMainService") - private MapMainService MapMainService; + private MapMainService mapMainService; //입력시스템 서비스 @Resource(name ="AppMainService") @@ -363,4 +367,120 @@ public class MapMainController extends BaseController { }; + + @RequestMapping(value = "/map/sichudanNew.do") + public String sichudanNew(ModelMap model, HttpServletRequest request, HttpServletResponse response, @RequestParam Map params) throws Exception { + String code = String.valueOf(params.get("code")); + + String data = ""; + try { + String[] hCodes = code.split(","); + for (int i = 0; i < hCodes.length; i++) { + data = data + hCodes[i].trim() + ","; + } + data = data.substring(0, data.length() - 1); + } catch (NumberFormatException e) { + //logger.debug("error", e); + data = ""; + } catch (IndexOutOfBoundsException e) { + //logger.debug("error", e); + data = ""; + } catch (Exception e) { + //logger.debug("error", e); + data = ""; + } + + model.put("data", data); + return "/sgis/map/mapInformation/sichudanNew"; + } + + @RequestMapping(value = "/map/getSichudanData.do", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE }) + @ResponseBody + public JSONObject getSichudanData(ModelMap model, HttpServletRequest request, HttpServletResponse response, @RequestParam Map params) throws Exception { + StringBuffer sb = request.getRequestURL(); + String url = sb.substring(0, sb.lastIndexOf("/")); + + String code = String.valueOf(params.get("code")); + + + JSONObject responseJson = new JSONObject(); + responseJson.put("jsonView", getSectionData(code)); + return responseJson; + } + + public JSONObject getSectionData(String code) throws Exception { + + code = code.trim(); + + Map params = new HashMap(); + + + String[] bussinessNHoleCode = code.split("\\|\\|"); + + params.put("businessCode", bussinessNHoleCode[0]); + params.put("holeCode", bussinessNHoleCode[1]); + + + EgovMap general = mapMainService.getGeneralData(params); + String[] values = String.valueOf(general.get("vlu")).split("\\|"); + + JSONObject resultJson = new JSONObject(); + resultJson.put("PCODE", values[0]); + resultJson.put("ALTITUDE", values[1]); + resultJson.put("DEPTH", values[2]); + + JSONObject position = new JSONObject(); + position.put("X", values[3]); + position.put("Y", values[4]); + + resultJson.put("TM", position); + + position = new JSONObject(); + position.put("X", values[5]); + position.put("Y", values[6]); + + resultJson.put("LL", position); + + resultJson.put("PNAME", values[7]); + resultJson.put("WATER", values[8]); + + if (values.length == 10) { + resultJson.put("PCOM", values[9]); + } else { + resultJson.put("PCOM", ""); + } + + JSONObject generalData = resultJson; + generalData.put("HCODE", code); + + List linkLayerData = mapMainService.getLinkLayerData(params); + //generalData.put("LAYER", listmap_to_json_string(linkLayerData)); + generalData.put("LAYER", linkLayerData); + + List SPTData = mapMainService.getSPTData(params); + //generalData.put("SPT", listmap_to_json_string(SPTData)); + generalData.put("SPT", SPTData); + + List sampleData = mapMainService.getSampleData(params); + //generalData.put("SAMPLE", listmap_to_json_string(sampleData)); + generalData.put("SAMPLE", sampleData); + + return generalData; + + } + + public String listmap_to_json_string(List list) { + JSONArray json_arr = new JSONArray(); + for (Map map : list) { + JSONObject json_obj = new JSONObject(); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + json_obj.put(key, value); + } + json_arr.add(json_obj); + } + return json_arr.toString(); + } + } diff --git a/src/main/resources/egovframework/mapper/sgis/map/MapMainMapper.xml b/src/main/resources/egovframework/mapper/sgis/map/MapMainMapper.xml index fe4e173..e496b63 100644 --- a/src/main/resources/egovframework/mapper/sgis/map/MapMainMapper.xml +++ b/src/main/resources/egovframework/mapper/sgis/map/MapMainMapper.xml @@ -54,4 +54,464 @@ ORDER BY HOL_COD ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/jsp/sgis/map/mapInformation/sichudanNew.jsp b/src/main/webapp/WEB-INF/jsp/sgis/map/mapInformation/sichudanNew.jsp new file mode 100644 index 0000000..d16cb2b --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/sgis/map/mapInformation/sichudanNew.jsp @@ -0,0 +1,358 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> + + + + + 스마트지반정보관리 시스템 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+ +
+ +
+

지반 단면도

+
+ +
+
+ + +
+
+ +
+
+
+
+
    +
  • 이동마우스 왼쪽 드래그, 확대L-Shift + 마우스 왼쪽 드래그
  • +
  • 시료를 채취한 부분으로 실내시험 결과를 확인 할 수 있습니다.
  • +
  • 지반주상도 정보를 확인 하실 수 있습니다.
  • +
  • 지반단면도에 대한 XML 데이터를 보실 수 있습니다.
  • +
+
+
+
    +
  • + + + +
  • +
  • + + +
  • +
  • + + + +
  • +
+
+
+
+
+
+

지층 색상표

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
색상USCS분류지층명
GW자갈입도 좋은 자갈
GP입도 나쁜 자갈
GM실트질 자갈
GC점토질 자갈
SW모래입도 좋은 모래
SP입도 나쁜 모래
SM실트질 모래
SC점토질 모래
ML실트무기질 실트, 극세사
MH무기질 실트
CL점토무기질, 자갈질 점토
CH고소성 무기질 점토
OH중소성 유기질 점토
OL유기질 실트
PT이탄 및 고유기질토
WR풍화암
SR연암
MR보통암
HR경암
XR극경암
ET기타
+
+ +
+
+ +
+ +
+ + +
+ +
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/sgis/map/mapMain.jsp b/src/main/webapp/WEB-INF/jsp/sgis/map/mapMain.jsp index 8ece7a3..2b84b23 100644 --- a/src/main/webapp/WEB-INF/jsp/sgis/map/mapMain.jsp +++ b/src/main/webapp/WEB-INF/jsp/sgis/map/mapMain.jsp @@ -181,7 +181,7 @@ } $(document).ready(function () { $("#projectStartDate").kendoDatePicker({ - value : new Date(), + value : new Date("1990-01-01T00:00:00.000+09:00"), culture: "ko-KR", format : "yyyy-MM-dd" }); @@ -256,7 +256,7 @@ var business_process_data = ${codeJson_business_process_code}; // 사업 공정 코드 $(document).ready(function () { $("#inputYmdTo").kendoDatePicker({ - value : new Date(), + value : new Date("1990-01-01T00:00:00.000+09:00"), culture: "ko-KR", format : "yyyy-MM-dd" }); @@ -368,17 +368,34 @@ 영역선택 - -
  • - - DEM 시계열 조회 - -
  • + +
  • + + DEM 시계열 조회 + +
  • +
  • + 지반단면도 + 지반주상도 + +
  • diff --git a/src/main/webapp/WEB-INF/jsp/tiles/attribute/app.submenu.jsp b/src/main/webapp/WEB-INF/jsp/tiles/attribute/app.submenu.jsp index 6756eb7..c93d9d6 100644 --- a/src/main/webapp/WEB-INF/jsp/tiles/attribute/app.submenu.jsp +++ b/src/main/webapp/WEB-INF/jsp/tiles/attribute/app.submenu.jsp @@ -330,7 +330,7 @@ + + 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", + 'EPSG:3875': "+title= Google Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs" +}; +Proj4js.defs['EPSG:3785'] = Proj4js.defs['EPSG:3875']; //maintain backward compat, official code is 3875 +Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3875']; +Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3875']; +Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3875']; + +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 (var 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) { + 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 Schreiber +// 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); + }, + + //code from the PROJ.4 pj_mlfn.c file; this may be useful for other projections + pj_enfn: function(es) { + var en = new Array(); + en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08))); + en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08))); + var t = es * es; + en[2] = t * (this.C44 - es * (this.C46 + es * this.C48)); + t *= es; + en[3] = t * (this.C66 - es * this.C68); + en[4] = t * es * this.C88; + return en; + }, + + pj_mlfn: function(phi, sphi, cphi, en) { + cphi *= sphi; + sphi *= sphi; + return(en[0] * phi - cphi * (en[1] + sphi*(en[2]+ sphi*(en[3] + sphi*en[4])))); + }, + + pj_inv_mlfn: function(arg, es, en) { + var k = 1./(1.-es); + var phi = arg; + for (var i = Proj4js.common.MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */ + var s = Math.sin(phi); + var t = 1. - es * s * s; + //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg; + //phi -= t * (t * Math.sqrt(t)) * k; + t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k; + phi -= t; + if (Math.abs(t) < Proj4js.common.EPSLN) + return phi; + } + Proj4js.reportError("cass:pj_inv_mlfn: Convergence error"); + return phi; + }, + +/* meridinal distance for ellipsoid and inverse +** 8th degree - accurate to < 1e-5 meters when used in conjuction +** with typical major axis values. +** Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds. +*/ + C00: 1.0, + C02: .25, + C04: .046875, + C06: .01953125, + C08: .01068115234375, + C22: .75, + C44: .46875, + C46: .01302083333333333333, + C48: .00712076822916666666, + C66: .36458333333333333333, + C68: .00569661458333333333, + C88: .3076171875 + +}; + +/** 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 TRUE if the two datums match, otherwise 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 || + dest.datum_type == Proj4js.common.PJD_GRIDSHIFT ) { + alert("ERROR: Grid shift transformations are not implemented."); + return false + } 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' && typeof y == 'undefined') { + 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 + +//lookup table to go from the projection name in WKT to the Proj4js projection name +//build this out as required +Proj4js.wktProjections = { + "Lambert Tangential Conformal Conic Projection": "lcc", + "Mercator": "merc", + "Popular Visualisation Pseudo Mercator": "merc", + "Mercator_1SP": "merc", + "Transverse_Mercator": "tmerc", + "Transverse Mercator": "tmerc", + "Lambert Azimuthal Equal Area": "laea", + "Universal Transverse Mercator System": "utm" +}; + + +/* ====================================================================== + projCode/aea.js + ====================================================================== */ + +/******************************************************************************* +NAME ALBERS CONICAL EQUAL AREA + +PURPOSE: Transforms input longitude and latitude to Easting and Northing + for the Albers Conical Equal Area projection. The longitude + and latitude must be in radians. The Easting and Northing + values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan, Feb, 1992 + +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. +*******************************************************************************/ + + +Proj4js.Proj.aea = { + init : function() { + + if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) { + Proj4js.reportError("aeaInitEqualLatitudes"); + return; + } + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2); + this.e3 = Math.sqrt(this.es); + + this.sin_po=Math.sin(this.lat1); + this.cos_po=Math.cos(this.lat1); + this.t1=this.sin_po; + this.con = this.sin_po; + this.ms1 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po); + this.qs1 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po); + + this.sin_po=Math.sin(this.lat2); + this.cos_po=Math.cos(this.lat2); + this.t2=this.sin_po; + this.ms2 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po); + this.qs2 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po); + + this.sin_po=Math.sin(this.lat0); + this.cos_po=Math.cos(this.lat0); + this.t3=this.sin_po; + this.qs0 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po); + + if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) { + this.ns0 = (this.ms1 * this.ms1 - this.ms2 *this.ms2)/ (this.qs2 - this.qs1); + } else { + this.ns0 = this.con; + } + this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1; + this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0)/this.ns0; + }, + +/* Albers Conical Equal Area forward equations--mapping lat,long to x,y + -------------------------------------------------------------------*/ + forward: function(p){ + + var lon=p.x; + var lat=p.y; + + this.sin_phi=Math.sin(lat); + this.cos_phi=Math.cos(lat); + + var qs = Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi); + var rh1 =this.a * Math.sqrt(this.c - this.ns0 * qs)/this.ns0; + var theta = this.ns0 * Proj4js.common.adjust_lon(lon - this.long0); + var x = rh1 * Math.sin(theta) + this.x0; + var y = this.rh - rh1 * Math.cos(theta) + this.y0; + + p.x = x; + p.y = y; + return p; + }, + + + inverse: function(p) { + var rh1,qs,con,theta,lon,lat; + + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + if (this.ns0 >= 0) { + rh1 = Math.sqrt(p.x *p.x + p.y * p.y); + con = 1.0; + } else { + rh1 = -Math.sqrt(p.x * p.x + p.y *p.y); + con = -1.0; + } + theta = 0.0; + if (rh1 != 0.0) { + theta = Math.atan2(con * p.x, con * p.y); + } + con = rh1 * this.ns0 / this.a; + qs = (this.c - con * con) / this.ns0; + if (this.e3 >= 1e-10) { + con = 1 - .5 * (1.0 -this.es) * Math.log((1.0 - this.e3) / (1.0 + this.e3))/this.e3; + if (Math.abs(Math.abs(con) - Math.abs(qs)) > .0000000001 ) { + lat = this.phi1z(this.e3,qs); + } else { + if (qs >= 0) { + lat = .5 * Proj4js.common.PI; + } else { + lat = -.5 * Proj4js.common.PI; + } + } + } else { + lat = this.phi1z(this.e3,qs); + } + + lon = Proj4js.common.adjust_lon(theta/this.ns0 + this.long0); + p.x = lon; + p.y = lat; + return p; + }, + +/* Function to compute phi1, the latitude for the inverse of the + Albers Conical Equal-Area projection. +-------------------------------------------*/ + phi1z: function (eccent,qs) { + var sinphi, cosphi, con, com, dphi; + var phi = Proj4js.common.asinz(.5 * qs); + if (eccent < Proj4js.common.EPSLN) return phi; + + var eccnts = eccent * eccent; + for (var i = 1; i <= 25; i++) { + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + con = eccent * sinphi; + com = 1.0 - con * con; + dphi = .5 * com * com / cosphi * (qs / (1.0 - eccnts) - sinphi / com + .5 / eccent * Math.log((1.0 - con) / (1.0 + con))); + phi = phi + dphi; + if (Math.abs(dphi) <= 1e-7) return phi; + } + Proj4js.reportError("aea:phi1z:Convergence error"); + return null; + } + +}; + + + +/* ====================================================================== + projCode/sterea.js + ====================================================================== */ + + +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) { + var sinc, cosc, cosl, k; + 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 sinc, cosc, lon, lat, rho; + 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)) ) { + var 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; + } +}; + +/* ====================================================================== + projCode/poly.js + ====================================================================== */ + +/* Function to compute, phi4, the latitude for the inverse of the + Polyconic projection. +------------------------------------------------------------*/ +function phi4z (eccent,e0,e1,e2,e3,a,b,c,phi) { + var sinphi, sin2ph, tanphi, ml, mlp, con1, con2, con3, dphi, i; + + phi = a; + for (i = 1; i <= 15; i++) { + sinphi = Math.sin(phi); + tanphi = Math.tan(phi); + c = tanphi * Math.sqrt (1.0 - eccent * sinphi * sinphi); + sin2ph = Math.sin (2.0 * phi); + /* + ml = e0 * *phi - e1 * sin2ph + e2 * sin (4.0 * *phi); + mlp = e0 - 2.0 * e1 * cos (2.0 * *phi) + 4.0 * e2 * cos (4.0 * *phi); + */ + ml = e0 * phi - e1 * sin2ph + e2 * Math.sin (4.0 * phi) - e3 * Math.sin (6.0 * phi); + mlp = e0 - 2.0 * e1 * Math.cos (2.0 * phi) + 4.0 * e2 * Math.cos (4.0 * phi) - 6.0 * e3 * Math.cos (6.0 * phi); + con1 = 2.0 * ml + c * (ml * ml + b) - 2.0 * a * (c * ml + 1.0); + con2 = eccent * sin2ph * (ml * ml + b - 2.0 * a * ml) / (2.0 *c); + con3 = 2.0 * (a - ml) * (c * mlp - 2.0 / sin2ph) - 2.0 * mlp; + dphi = con1 / (con2 + con3); + phi += dphi; + if (Math.abs(dphi) <= .0000000001 ) return(phi); + } + Proj4js.reportError("phi4z: No convergence"); + return null; +} + + +/* Function to compute the constant e4 from the input of the eccentricity + of the spheroid, x. This constant is used in the Polar Stereographic + projection. +--------------------------------------------------------------------*/ +function e4fn(x) { + var con, com; + con = 1.0 + x; + com = 1.0 - x; + return (Math.sqrt((Math.pow(con,con))*(Math.pow(com,com)))); +} + + + + + +/******************************************************************************* +NAME POLYCONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Polyconic projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +Proj4js.Proj.poly = { + + /* Initialize the POLYCONIC projection + ----------------------------------*/ + init: function() { + var temp; /* temporary variable */ + if (this.lat0 == 0) this.lat0 = 90;//this.lat0 ca + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2);// devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles + this.e = Math.sqrt(this.es); + 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 = Proj4js.common.mlfn(this.e0, this.e1,this.e2, this.e3, this.lat0);//si que des zeros le calcul ne se fait pas + //if (!this.ml0) {this.ml0=0;} + }, + + + /* Polyconic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + forward: function(p) { + var sinphi, cosphi; /* sin and cos value */ + var al; /* temporary values */ + var c; /* temporary values */ + var con, ml; /* cone constant, small m */ + var ms; /* small m */ + var x,y; + + var lon=p.x; + var lat=p.y; + + con = Proj4js.common.adjust_lon(lon - this.long0); + if (Math.abs(lat) <= .0000001) { + x = this.x0 + this.a * con; + y = this.y0 - this.a * this.ml0; + } else { + sinphi = Math.sin(lat); + cosphi = Math.cos(lat); + + ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + ms = Proj4js.common.msfnz(this.e,sinphi,cosphi); + con = sinphi; + x = this.x0 + this.a * ms * Math.sin(con)/sinphi; + y = this.y0 + this.a * (ml - this.ml0 + ms * (1.0 - Math.cos(con))/sinphi); + } + + p.x=x; + p.y=y; + return p; + }, + + + /* Inverse equations + -----------------*/ + inverse: function(p) { + var sin_phi, cos_phi; /* sin and cos value */ + var al; /* temporary values */ + var b; /* temporary values */ + var c; /* temporary values */ + var con, ml; /* cone constant, small m */ + var iflg; /* error flag */ + var lon,lat; + p.x -= this.x0; + p.y -= this.y0; + al = this.ml0 + p.y/this.a; + iflg = 0; + + if (Math.abs(al) <= .0000001) { + lon = p.x/this.a + this.long0; + lat = 0.0; + } else { + b = al * al + (p.x/this.a) * (p.x/this.a); + iflg = phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat); + if (iflg != 1) return(iflg); + lon = Proj4js.common.adjust_lon((Proj4js.common.asinz(p.x * c / this.a) / Math.sin(lat)) + this.long0); + } + + p.x=lon; + p.y=lat; + return p; + } +}; + + + +/* ====================================================================== + projCode/equi.js + ====================================================================== */ + +/******************************************************************************* +NAME EQUIRECTANGULAR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Equirectangular projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ +Proj4js.Proj.equi = { + + init: function() { + if(!this.x0) this.x0=0; + if(!this.y0) this.y0=0; + if(!this.lat0) this.lat0=0; + if(!this.long0) this.long0=0; + ///this.t2; + }, + + + +/* Equirectangular forward equations--mapping lat,long to x,y + ---------------------------------------------------------*/ + forward: function(p) { + + var lon=p.x; + var lat=p.y; + + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var x = this.x0 +this. a * dlon *Math.cos(this.lat0); + var y = this.y0 + this.a * lat; + + this.t1=x; + this.t2=Math.cos(this.lat0); + p.x=x; + p.y=y; + return p; + }, //equiFwd() + + + +/* Equirectangular inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ + inverse: function(p) { + + p.x -= this.x0; + p.y -= this.y0; + var lat = p.y /this. a; + + if ( Math.abs(lat) > Proj4js.common.HALF_PI) { + Proj4js.reportError("equi:Inv:DataError"); + } + var lon = Proj4js.common.adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0))); + p.x=lon; + p.y=lat; + }//equiInv() +}; + + +/* ====================================================================== + projCode/merc.js + ====================================================================== */ + +/******************************************************************************* +NAME MERCATOR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS Nov, 1991 +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +//static double r_major = a; /* major axis */ +//static double r_minor = b; /* minor axis */ +//static double lon_center = long0; /* Center longitude (projection center) */ +//static double lat_origin = lat0; /* center latitude */ +//static double e,es; /* eccentricity constants */ +//static double m1; /* small value m */ +//static double false_northing = y0; /* y offset in meters */ +//static double false_easting = x0; /* x offset in meters */ +//scale_fact = k0 + +Proj4js.Proj.merc = { + init : function() { + //?this.temp = this.r_minor / this.r_major; + //this.temp = this.b / this.a; + //this.es = 1.0 - Math.sqrt(this.temp); + //this.e = Math.sqrt( this.es ); + //?this.m1 = Math.cos(this.lat_origin) / (Math.sqrt( 1.0 - this.es * Math.sin(this.lat_origin) * Math.sin(this.lat_origin))); + //this.m1 = Math.cos(0.0) / (Math.sqrt( 1.0 - this.es * Math.sin(0.0) * Math.sin(0.0))); + if (this.lat_ts) { + if (this.sphere) { + this.k0 = Math.cos(this.lat_ts); + } else { + this.k0 = Proj4js.common.msfnz(this.es, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); + } + } + }, + +/* Mercator forward equations--mapping lat,long to x,y + --------------------------------------------------*/ + + forward : function(p) { + //alert("ll2m coords : "+coords); + var lon = p.x; + var lat = p.y; + // convert to radians + if ( lat*Proj4js.common.R2D > 90.0 && + lat*Proj4js.common.R2D < -90.0 && + lon*Proj4js.common.R2D > 180.0 && + lon*Proj4js.common.R2D < -180.0) { + Proj4js.reportError("merc:forward: llInputOutOfRange: "+ lon +" : " + lat); + return null; + } + + var x,y; + if(Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) { + Proj4js.reportError("merc:forward: ll2mAtPoles"); + return null; + } else { + if (this.sphere) { + x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0); + y = this.y0 + this.a * this.k0 * Math.log(Math.tan(Proj4js.common.FORTPI + 0.5*lat)); + } else { + var sinphi = Math.sin(lat); + var ts = Proj4js.common.tsfnz(this.e,lat,sinphi); + x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0); + y = this.y0 - this.a * this.k0 * Math.log(ts); + } + p.x = x; + p.y = y; + return p; + } + }, + + + /* Mercator inverse equations--mapping x,y to lat/long + --------------------------------------------------*/ + inverse : function(p) { + + var x = p.x - this.x0; + var y = p.y - this.y0; + var lon,lat; + + if (this.sphere) { + lat = Proj4js.common.HALF_PI - 2.0 * Math.atan(Math.exp(-y / this.a * this.k0)); + } else { + var ts = Math.exp(-y / (this.a * this.k0)); + lat = Proj4js.common.phi2z(this.e,ts); + if(lat == -9999) { + Proj4js.reportError("merc:inverse: lat = -9999"); + return null; + } + } + lon = Proj4js.common.adjust_lon(this.long0+ x / (this.a * this.k0)); + + p.x = lon; + p.y = lat; + return p; + } +}; + + +/* ====================================================================== + projCode/utm.js + ====================================================================== */ + +/******************************************************************************* +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.utm = { + dependsOn : 'tmerc', + + init : function() { + if (!this.zone) { + Proj4js.reportError("utm:init: zone must be specified for UTM"); + return; + } + this.lat0 = 0.0; + this.long0 = ((6 * Math.abs(this.zone)) - 183) * Proj4js.common.D2R; + this.x0 = 500000.0; + this.y0 = this.utmSouth ? 10000000.0 : 0.0; + this.k0 = 0.9996; + + Proj4js.Proj['tmerc'].init.apply(this); + this.forward = Proj4js.Proj['tmerc'].forward; + this.inverse = Proj4js.Proj['tmerc'].inverse; + } +}; +/* ====================================================================== + projCode/eqdc.js + ====================================================================== */ + +/******************************************************************************* +NAME EQUIDISTANT CONIC + +PURPOSE: Transforms input longitude and latitude to Easting and Northing + for the Equidistant Conic projection. The longitude and + latitude must be in radians. The Easting and Northing values + will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +/* Variables common to all subroutines in this code file + -----------------------------------------------------*/ + +Proj4js.Proj.eqdc = { + +/* Initialize the Equidistant Conic projection + ------------------------------------------*/ + init: function() { + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + + if(!this.mode) this.mode=0;//chosen default mode + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2); + this.e = Math.sqrt(this.es); + 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.sinphi=Math.sin(this.lat1); + this.cosphi=Math.cos(this.lat1); + + this.ms1 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi); + this.ml1 = Proj4js.common.mlfn(this.e0, this.e1, this.e2,this.e3, this.lat1); + + /* format B + ---------*/ + if (this.mode != 0) { + if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) { + Proj4js.reportError("eqdc:Init:EqualLatitudes"); + //return(81); + } + this.sinphi=Math.sin(this.lat2); + this.cosphi=Math.cos(this.lat2); + + this.ms2 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi); + this.ml2 = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2); + if (Math.abs(this.lat1 - this.lat2) >= Proj4js.common.EPSLN) { + this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1); + } else { + this.ns = this.sinphi; + } + } else { + this.ns = this.sinphi; + } + this.g = this.ml1 + this.ms1/this.ns; + this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this. e2, this.e3, this.lat0); + this.rh = this.a * (this.g - this.ml0); + }, + + +/* Equidistant Conic forward equations--mapping lat,long to x,y + -----------------------------------------------------------*/ + forward: function(p) { + var lon=p.x; + var lat=p.y; + + /* Forward equations + -----------------*/ + var ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + var rh1 = this.a * (this.g - ml); + var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0); + + var x = this.x0 + rh1 * Math.sin(theta); + var y = this.y0 + this.rh - rh1 * Math.cos(theta); + p.x=x; + p.y=y; + return p; + }, + +/* Inverse equations + -----------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + var con, rh1; + if (this.ns >= 0) { + rh1 = Math.sqrt(p.x *p.x + p.y * p.y); + con = 1.0; + } else { + rh1 = -Math.sqrt(p.x *p. x +p. y * p.y); + con = -1.0; + } + var theta = 0.0; + if (rh1 != 0.0) theta = Math.atan2(con *p.x, con *p.y); + var ml = this.g - rh1 /this.a; + var lat = this.phi3z(ml,this.e0,this.e1,this.e2,this.e3); + var lon = Proj4js.common.adjust_lon(this.long0 + theta / this.ns); + + p.x=lon; + p.y=lat; + return p; + }, + +/* Function to compute latitude, phi3, for the inverse of the Equidistant + Conic projection. +-----------------------------------------------------------------*/ + phi3z: function(ml,e0,e1,e2,e3) { + var phi; + var dphi; + + phi = ml; + for (var i = 0; i < 15; i++) { + dphi = (ml + e1 * Math.sin(2.0 * phi) - e2 * Math.sin(4.0 * phi) + e3 * Math.sin(6.0 * phi))/ e0 - phi; + phi += dphi; + if (Math.abs(dphi) <= .0000000001) { + return phi; + } + } + Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations"); + return null; + } + + +}; +/* ====================================================================== + projCode/tmerc.js + ====================================================================== */ + +/******************************************************************************* +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 = Proj4js.common.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;true;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() +}; +/* ====================================================================== + defs/GOOGLE.js + ====================================================================== */ + +Proj4js.defs["GOOGLE"]="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"; +Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"]; +/* ====================================================================== + projCode/gstmerc.js + ====================================================================== */ + +Proj4js.Proj.gstmerc = { + init : function() { + + // array of: a, b, lon0, lat0, k0, x0, y0 + var temp= this.b / this.a; + this.e= Math.sqrt(1.0 - temp*temp); + this.lc= this.long0; + this.rs= Math.sqrt(1.0+this.e*this.e*Math.pow(Math.cos(this.lat0),4.0)/(1.0-this.e*this.e)); + var sinz= Math.sin(this.lat0); + var pc= Math.asin(sinz/this.rs); + var sinzpc= Math.sin(pc); + this.cp= Proj4js.common.latiso(0.0,pc,sinzpc)-this.rs*Proj4js.common.latiso(this.e,this.lat0,sinz); + this.n2= this.k0*this.a*Math.sqrt(1.0-this.e*this.e)/(1.0-this.e*this.e*sinz*sinz); + this.xs= this.x0; + this.ys= this.y0-this.n2*pc; + + if (!this.title) this.title = "Gauss Schreiber transverse mercator"; + }, + + + // forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + forward : function(p) { + + var lon= p.x; + var lat= p.y; + + var L= this.rs*(lon-this.lc); + var Ls= this.cp+(this.rs*Proj4js.common.latiso(this.e,lat,Math.sin(lat))); + var lat1= Math.asin(Math.sin(L)/Proj4js.common.cosh(Ls)); + var Ls1= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1)); + p.x= this.xs+(this.n2*Ls1); + p.y= this.ys+(this.n2*Math.atan(Proj4js.common.sinh(Ls)/Math.cos(L))); + return p; + }, + + // inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + inverse : function(p) { + + var x= p.x; + var y= p.y; + + var L= Math.atan(Proj4js.common.sinh((x-this.xs)/this.n2)/Math.cos((y-this.ys)/this.n2)); + var lat1= Math.asin(Math.sin((y-this.ys)/this.n2)/Proj4js.common.cosh((x-this.xs)/this.n2)); + var LC= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1)); + p.x= this.lc+L/this.rs; + p.y= Proj4js.common.invlatiso(this.e,(LC-this.cp)/this.rs); + return p; + } + +}; +/* ====================================================================== + projCode/ortho.js + ====================================================================== */ + +/******************************************************************************* +NAME ORTHOGRAPHIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Orthographic projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +Proj4js.Proj.ortho = { + + /* Initialize the Orthographic projection + -------------------------------------*/ + init: function(def) { + //double temp; /* temporary variable */ + + /* Place parameters in static storage for common use + -------------------------------------------------*/; + this.sin_p14=Math.sin(this.lat0); + this.cos_p14=Math.cos(this.lat0); + }, + + + /* Orthographic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + forward: function(p) { + var sinphi, cosphi; /* sin and cos value */ + var dlon; /* delta longitude value */ + var coslon; /* cos of longitude */ + var ksp; /* scale factor */ + var g; + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + dlon = Proj4js.common.adjust_lon(lon - this.long0); + + sinphi=Math.sin(lat); + cosphi=Math.cos(lat); + + coslon = Math.cos(dlon); + g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; + ksp = 1.0; + if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) { + var x = this.a * ksp * cosphi * Math.sin(dlon); + var y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); + } else { + Proj4js.reportError("orthoFwdPointError"); + } + p.x=x; + p.y=y; + return p; + }, + + + inverse: function(p) { + var rh; /* height above ellipsoid */ + var z; /* angle */ + var sinz,cosz; /* sin of z and cos of z */ + var temp; + var con; + var lon , lat; + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + rh = Math.sqrt(p.x * p.x + p.y * p.y); + if (rh > this.a + .0000001) { + Proj4js.reportError("orthoInvDataError"); + } + z = Proj4js.common.asinz(rh / this.a); + + sinz=Math.sin(z); + cosz=Math.cos(z); + + lon = this.long0; + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.lat0; + } + lat = Proj4js.common.asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14)/rh); + con = Math.abs(this.lat0) - Proj4js.common.HALF_PI; + if (Math.abs(con) <= Proj4js.common.EPSLN) { + if (this.lat0 >= 0) { + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y)); + } else { + lon = Proj4js.common.adjust_lon(this.long0 -Math.atan2(-p.x, p.y)); + } + } + con = cosz - this.sin_p14 * Math.sin(lat); + p.x=lon; + p.y=lat; + return p; + } +}; + + +/* ====================================================================== + projCode/krovak.js + ====================================================================== */ + +/** + NOTES: According to EPSG the full Krovak projection method should have + the following parameters. Within PROJ.4 the azimuth, and pseudo + standard parallel are hardcoded in the algorithm and can't be + altered from outside. The others all have defaults to match the + common usage with Krovak projection. + + lat_0 = latitude of centre of the projection + + lon_0 = longitude of centre of the projection + + ** = azimuth (true) of the centre line passing through the centre of the projection + + ** = latitude of pseudo standard parallel + + k = scale factor on the pseudo standard parallel + + x_0 = False Easting of the centre of the projection at the apex of the cone + + y_0 = False Northing of the centre of the projection at the apex of the cone + + **/ + +Proj4js.Proj.krovak = { + + init: function() { + /* we want Bessel as fixed ellipsoid */ + this.a = 6377397.155; + this.es = 0.006674372230614; + this.e = Math.sqrt(this.es); + /* if latitude of projection center is not set, use 49d30'N */ + if (!this.lat0) { + this.lat0 = 0.863937979737193; + } + if (!this.long0) { + this.long0 = 0.7417649320975901 - 0.308341501185665; + } + /* if scale not set default to 0.9999 */ + if (!this.k0) { + this.k0 = 0.9999; + } + this.s45 = 0.785398163397448; /* 45 */ + this.s90 = 2 * this.s45; + this.fi0 = this.lat0; /* Latitude of projection centre 49 30' */ + /* Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128, + e2=0.006674372230614; + */ + this.e2 = this.es; /* 0.006674372230614; */ + this.e = Math.sqrt(this.e2); + this.alfa = Math.sqrt(1. + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1. - this.e2)); + this.uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */ + this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa); + this.g = Math.pow( (1. + this.e * Math.sin(this.fi0)) / (1. - this.e * Math.sin(this.fi0)) , this.alfa * this.e / 2. ); + this.k = Math.tan( this.u0 / 2. + this.s45) / Math.pow (Math.tan(this.fi0 / 2. + this.s45) , this.alfa) * this.g; + this.k1 = this.k0; + this.n0 = this.a * Math.sqrt(1. - this.e2) / (1. - this.e2 * Math.pow(Math.sin(this.fi0), 2)); + this.s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78 30'00" N */ + this.n = Math.sin(this.s0); + this.ro0 = this.k1 * this.n0 / Math.tan(this.s0); + this.ad = this.s90 - this.uq; + }, + + /* ellipsoid */ + /* calculate xy from lat/lon */ + /* Constants, identical to inverse transform function */ + forward: function(p) { + var gfi, u, deltav, s, d, eps, ro; + var lon = p.x; + var lat = p.y; + var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude + /* Transformation */ + gfi = Math.pow ( ((1. + this.e * Math.sin(lat)) / (1. - this.e * Math.sin(lat))) , (this.alfa * this.e / 2.)); + u= 2. * (Math.atan(this.k * Math.pow( Math.tan(lat / 2. + this.s45), this.alfa) / gfi)-this.s45); + deltav = - delta_lon * this.alfa; + s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav)); + d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s)); + eps = this.n * d; + ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2. + this.s45) , this.n) / Math.pow(Math.tan(s / 2. + this.s45) , this.n); + /* x and y are reverted! */ + //p.y = ro * Math.cos(eps) / a; + //p.x = ro * Math.sin(eps) / a; + p.y = ro * Math.cos(eps) / 1.0; + p.x = ro * Math.sin(eps) / 1.0; + + if(this.czech) { + p.y *= -1.0; + p.x *= -1.0; + } + return (p); + }, + + /* calculate lat/lon from xy */ + inverse: function(p) { + /* Constants, identisch wie in der Umkehrfunktion */ + var u, deltav, s, d, eps, ro, fi1; + var ok; + + /* Transformation */ + /* revert y, x*/ + var tmp = p.x; + p.x=p.y; + p.y=tmp; + if(this.czech) { + p.y *= -1.0; + p.x *= -1.0; + } + ro = Math.sqrt(p.x * p.x + p.y * p.y); + eps = Math.atan2(p.y, p.x); + d = eps / Math.sin(this.s0); + s = 2. * (Math.atan( Math.pow(this.ro0 / ro, 1. / this.n) * Math.tan(this.s0 / 2. + this.s45)) - this.s45); + u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d)); + deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u)); + p.x = this.long0 - deltav / this.alfa; + /* ITERATION FOR lat */ + fi1 = u; + ok = 0; + var iter = 0; + do { + p.y = 2. * ( Math.atan( Math.pow( this.k, -1. / this.alfa) * + Math.pow( Math.tan(u / 2. + this.s45) , 1. / this.alfa) * + Math.pow( (1. + this.e * Math.sin(fi1)) / (1. - this.e * Math.sin(fi1)) , this.e / 2.) + ) - this.s45); + if (Math.abs(fi1 - p.y) < 0.0000000001) ok=1; + fi1 = p.y; + iter += 1; + } while (ok==0 && iter < 15); + if (iter >= 15) { + Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations"); + //console.log('iter:', iter); + return null; + } + + return (p); + } +}; +/* ====================================================================== + projCode/somerc.js + ====================================================================== */ + +/******************************************************************************* +NAME SWISS OBLIQUE MERCATOR + +PURPOSE: Swiss projection. +WARNING: X and Y are inverted (weird) in the swiss coordinate system. Not + here, since we want X to be horizontal and Y vertical. + +ALGORITHM REFERENCES +1. "Formules et constantes pour le Calcul pour la + projection cylindrique conforme à axe oblique et pour la transformation entre + des systèmes de référence". + http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf + +*******************************************************************************/ + +Proj4js.Proj.somerc = { + + init: function() { + var phy0 = this.lat0; + this.lambda0 = this.long0; + var sinPhy0 = Math.sin(phy0); + var semiMajorAxis = this.a; + var invF = this.rf; + var flattening = 1 / invF; + var e2 = 2 * flattening - Math.pow(flattening, 2); + var e = this.e = Math.sqrt(e2); + this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2.0)); + this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4.0)); + this.b0 = Math.asin(sinPhy0 / this.alpha); + this.K = Math.log(Math.tan(Math.PI / 4.0 + this.b0 / 2.0)) + - this.alpha + * Math.log(Math.tan(Math.PI / 4.0 + phy0 / 2.0)) + + this.alpha + * e / 2 + * Math.log((1 + e * sinPhy0) + / (1 - e * sinPhy0)); + }, + + + forward: function(p) { + var Sa1 = Math.log(Math.tan(Math.PI / 4.0 - p.y / 2.0)); + var Sa2 = this.e / 2.0 + * Math.log((1 + this.e * Math.sin(p.y)) + / (1 - this.e * Math.sin(p.y))); + var S = -this.alpha * (Sa1 + Sa2) + this.K; + + // spheric latitude + var b = 2.0 * (Math.atan(Math.exp(S)) - Math.PI / 4.0); + + // spheric longitude + var I = this.alpha * (p.x - this.lambda0); + + // psoeudo equatorial rotation + var rotI = Math.atan(Math.sin(I) + / (Math.sin(this.b0) * Math.tan(b) + + Math.cos(this.b0) * Math.cos(I))); + + var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) - + Math.sin(this.b0) * Math.cos(b) * Math.cos(I)); + + p.y = this.R / 2.0 + * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) + + this.y0; + p.x = this.R * rotI + this.x0; + return p; + }, + + inverse: function(p) { + var Y = p.x - this.x0; + var X = p.y - this.y0; + + var rotI = Y / this.R; + var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4.0); + + var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB) + + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI)); + var I = Math.atan(Math.sin(rotI) + / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) + * Math.tan(rotB))); + + var lambda = this.lambda0 + I / this.alpha; + + var S = 0.0; + var phy = b; + var prevPhy = -1000.0; + var iteration = 0; + while (Math.abs(phy - prevPhy) > 0.0000001) + { + if (++iteration > 20) + { + Proj4js.reportError("omercFwdInfinity"); + return; + } + //S = Math.log(Math.tan(Math.PI / 4.0 + phy / 2.0)); + S = 1.0 + / this.alpha + * (Math.log(Math.tan(Math.PI / 4.0 + b / 2.0)) - this.K) + + this.e + * Math.log(Math.tan(Math.PI / 4.0 + + Math.asin(this.e * Math.sin(phy)) + / 2.0)); + prevPhy = phy; + phy = 2.0 * Math.atan(Math.exp(S)) - Math.PI / 2.0; + } + + p.x = lambda; + p.y = phy; + return p; + } +}; +/* ====================================================================== + projCode/stere.js + ====================================================================== */ + + +// Initialize the Stereographic projection + +Proj4js.Proj.stere = { + ssfn_: function(phit, sinphi, eccen) { + sinphi *= eccen; + return (Math.tan (.5 * (Proj4js.common.HALF_PI + phit)) * Math.pow((1. - sinphi) / (1. + sinphi), .5 * eccen)); + }, + TOL: 1.e-8, + NITER: 8, + CONV: 1.e-10, + S_POLE: 0, + N_POLE: 1, + OBLIQ: 2, + EQUIT: 3, + + init: function() { + this.phits = this.lat_ts ? this.lat_ts : Proj4js.common.HALF_PI; + var t = Math.abs(this.lat0); + if ((Math.abs(t) - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) { + this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE; + } else { + this.mode = t > Proj4js.common.EPSLN ? this.OBLIQ : this.EQUIT; + } + this.phits = Math.abs(this.phits); + if (this.es) { + var X; + + switch (this.mode) { + case this.N_POLE: + case this.S_POLE: + if (Math.abs(this.phits - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) { + this.akm1 = 2. * this.k0 / Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e)); + } else { + t = Math.sin(this.phits); + this.akm1 = Math.cos(this.phits) / Proj4js.common.tsfnz(this.e, this.phits, t); + t *= this.e; + this.akm1 /= Math.sqrt(1. - t * t); + } + break; + case this.EQUIT: + this.akm1 = 2. * this.k0; + break; + case this.OBLIQ: + t = Math.sin(this.lat0); + X = 2. * Math.atan(this.ssfn_(this.lat0, t, this.e)) - Proj4js.common.HALF_PI; + t *= this.e; + this.akm1 = 2. * this.k0 * Math.cos(this.lat0) / Math.sqrt(1. - t * t); + this.sinX1 = Math.sin(X); + this.cosX1 = Math.cos(X); + break; + } + } else { + switch (this.mode) { + case this.OBLIQ: + this.sinph0 = Math.sin(this.lat0); + this.cosph0 = Math.cos(this.lat0); + case this.EQUIT: + this.akm1 = 2. * this.k0; + break; + case this.S_POLE: + case this.N_POLE: + this.akm1 = Math.abs(this.phits - Proj4js.common.HALF_PI) >= Proj4js.common.EPSLN ? + Math.cos(this.phits) / Math.tan(Proj4js.common.FORTPI - .5 * this.phits) : + 2. * this.k0 ; + break; + } + } + }, + +// Stereographic forward equations--mapping lat,long to x,y + forward: function(p) { + var lon = p.x; + lon = Proj4js.common.adjust_lon(lon - this.long0); + var lat = p.y; + var x, y; + + if (this.sphere) { + var sinphi, cosphi, coslam, sinlam; + + sinphi = Math.sin(lat); + cosphi = Math.cos(lat); + coslam = Math.cos(lon); + sinlam = Math.sin(lon); + switch (this.mode) { + case this.EQUIT: + y = 1. + cosphi * coslam; + if (y <= Proj4js.common.EPSLN) { + Proj4js.reportError("stere:forward:Equit"); + } + y = this.akm1 / y; + x = y * cosphi * sinlam; + y *= sinphi; + break; + case this.OBLIQ: + y = 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam; + if (y <= Proj4js.common.EPSLN) { + Proj4js.reportError("stere:forward:Obliq"); + } + y = this.akm1 / y; + x = y * cosphi * sinlam; + y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam; + break; + case this.N_POLE: + coslam = -coslam; + lat = -lat; + //Note no break here so it conitnues through S_POLE + case this.S_POLE: + if (Math.abs(lat - Proj4js.common.HALF_PI) < this.TOL) { + Proj4js.reportError("stere:forward:S_POLE"); + } + y = this.akm1 * Math.tan(Proj4js.common.FORTPI + .5 * lat); + x = sinlam * y; + y *= coslam; + break; + } + } else { + coslam = Math.cos(lon); + sinlam = Math.sin(lon); + sinphi = Math.sin(lat); + var sinX, cosX; + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + var Xt = 2. * Math.atan(this.ssfn_(lat, sinphi, this.e)); + sinX = Math.sin(Xt - Proj4js.common.HALF_PI); + cosX = Math.cos(Xt); + } + switch (this.mode) { + case this.OBLIQ: + var A = this.akm1 / (this.cosX1 * (1. + this.sinX1 * sinX + this.cosX1 * cosX * coslam)); + y = A * (this.cosX1 * sinX - this.sinX1 * cosX * coslam); + x = A * cosX; + break; + case this.EQUIT: + var A = 2. * this.akm1 / (1. + cosX * coslam); + y = A * sinX; + x = A * cosX; + break; + case this.S_POLE: + lat = -lat; + coslam = - coslam; + sinphi = -sinphi; + case this.N_POLE: + x = this.akm1 * Proj4js.common.tsfnz(this.e, lat, sinphi); + y = - x * coslam; + break; + } + x = x * sinlam; + } + p.x = x*this.a + this.x0; + p.y = y*this.a + this.y0; + return p; + }, + + +//* Stereographic inverse equations--mapping x,y to lat/long + inverse: function(p) { + var x = (p.x - this.x0)/this.a; /* descale and de-offset */ + var y = (p.y - this.y0)/this.a; + var lon, lat; + + var cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, pi2=0.0; + var i; + + if (this.sphere) { + var c, rh, sinc, cosc; + + rh = Math.sqrt(x*x + y*y); + c = 2. * Math.atan(rh / this.akm1); + sinc = Math.sin(c); + cosc = Math.cos(c); + lon = 0.; + switch (this.mode) { + case this.EQUIT: + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = 0.; + } else { + lat = Math.asin(y * sinc / rh); + } + if (cosc != 0. || x != 0.) lon = Math.atan2(x * sinc, cosc * rh); + break; + case this.OBLIQ: + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.phi0; + } else { + lat = Math.asin(cosc * this.sinph0 + y * sinc * this.cosph0 / rh); + } + c = cosc - this.sinph0 * Math.sin(lat); + if (c != 0. || x != 0.) { + lon = Math.atan2(x * sinc * this.cosph0, c * rh); + } + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.phi0; + } else { + lat = Math.asin(this.mode == this.S_POLE ? -cosc : cosc); + } + lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y); + break; + } + p.x = Proj4js.common.adjust_lon(lon + this.long0); + p.y = lat; + } else { + rho = Math.sqrt(x*x + y*y); + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + tp = 2. * Math.atan2(rho * this.cosX1 , this.akm1); + cosphi = Math.cos(tp); + sinphi = Math.sin(tp); + if( rho == 0.0 ) { + phi_l = Math.asin(cosphi * this.sinX1); + } else { + phi_l = Math.asin(cosphi * this.sinX1 + (y * sinphi * this.cosX1 / rho)); + } + + tp = Math.tan(.5 * (Proj4js.common.HALF_PI + phi_l)); + x *= sinphi; + y = rho * this.cosX1 * cosphi - y * this.sinX1* sinphi; + pi2 = Proj4js.common.HALF_PI; + halfe = .5 * this.e; + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + tp = - rho / this.akm1; + phi_l = Proj4js.common.HALF_PI - 2. * Math.atan(tp); + pi2 = -Proj4js.common.HALF_PI; + halfe = -.5 * this.e; + break; + } + for (i = this.NITER; i--; phi_l = lat) { //check this + sinphi = this.e * Math.sin(phi_l); + lat = 2. * Math.atan(tp * Math.pow((1.+sinphi)/(1.-sinphi), halfe)) - pi2; + if (Math.abs(phi_l - lat) < this.CONV) { + if (this.mode == this.S_POLE) lat = -lat; + lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y); + p.x = Proj4js.common.adjust_lon(lon + this.long0); + p.y = lat; + return p; + } + } + } + } +}; +/* ====================================================================== + projCode/nzmg.js + ====================================================================== */ + +/******************************************************************************* +NAME NEW ZEALAND MAP GRID + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the New Zealand Map Grid projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + + +ALGORITHM REFERENCES + +1. Department of Land and Survey Technical Circular 1973/32 + http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf + +2. OSG Technical Report 4.1 + http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf + + +IMPLEMENTATION NOTES + +The two references use different symbols for the calculated values. This +implementation uses the variable names similar to the symbols in reference [1]. + +The alogrithm uses different units for delta latitude and delta longitude. +The delta latitude is assumed to be in units of seconds of arc x 10^-5. +The delta longitude is the usual radians. Look out for these conversions. + +The algorithm is described using complex arithmetic. There were three +options: + * find and use a Javascript library for complex arithmetic + * write my own complex library + * expand the complex arithmetic by hand to simple arithmetic + +This implementation has expanded the complex multiplication operations +into parallel simple arithmetic operations for the real and imaginary parts. +The imaginary part is way over to the right of the display; this probably +violates every coding standard in the world, but, to me, it makes it much +more obvious what is going on. + +The following complex operations are used: + - addition + - multiplication + - division + - complex number raised to integer power + - summation + +A summary of complex arithmetic operations: + (from http://en.wikipedia.org/wiki/Complex_arithmetic) + addition: (a + bi) + (c + di) = (a + c) + (b + d)i + subtraction: (a + bi) - (c + di) = (a - c) + (b - d)i + multiplication: (a + bi) x (c + di) = (ac - bd) + (bc + ad)i + division: (a + bi) / (c + di) = [(ac + bd)/(cc + dd)] + [(bc - ad)/(cc + dd)]i + +The algorithm needs to calculate summations of simple and complex numbers. This is +implemented using a for-loop, pre-loading the summed value to zero. + +The algorithm needs to calculate theta^2, theta^3, etc while doing a summation. +There are three possible implementations: + - use Math.pow in the summation loop - except for complex numbers + - precalculate the values before running the loop + - calculate theta^n = theta^(n-1) * theta during the loop +This implementation uses the third option for both real and complex arithmetic. + +For example + psi_n = 1; + sum = 0; + for (n = 1; n <=6; n++) { + psi_n1 = psi_n * psi; // calculate psi^(n+1) + psi_n = psi_n1; + sum = sum + A[n] * psi_n; + } + + +TEST VECTORS + +NZMG E, N: 2487100.638 6751049.719 metres +NZGD49 long, lat: 172.739194 -34.444066 degrees + +NZMG E, N: 2486533.395 6077263.661 metres +NZGD49 long, lat: 172.723106 -40.512409 degrees + +NZMG E, N: 2216746.425 5388508.765 metres +NZGD49 long, lat: 169.172062 -46.651295 degrees + +Note that these test vectors convert from NZMG metres to lat/long referenced +to NZGD49, not the more usual WGS84. The difference is about 70m N/S and about +10m E/W. + +These test vectors are provided in reference [1]. Many more test +vectors are available in + http://www.linz.govt.nz/docs/topography/topographicdata/placenamesdatabase/nznamesmar08.zip +which is a catalog of names on the 260-series maps. + + +EPSG CODES + +NZMG EPSG:27200 +NZGD49 EPSG:4272 + +http://spatialreference.org/ defines these as + Proj4js.defs["EPSG:4272"] = "+proj=longlat +ellps=intl +datum=nzgd49 +no_defs "; + Proj4js.defs["EPSG:27200"] = "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +datum=nzgd49 +units=m +no_defs "; + + +LICENSE + Copyright: Stephen Irons 2008 + Released under terms of the LGPL as per: http://www.gnu.org/copyleft/lesser.html + +*******************************************************************************/ + + +/** + Initialize New Zealand Map Grip projection +*/ + +Proj4js.Proj.nzmg = { + + /** + * iterations: Number of iterations to refine inverse transform. + * 0 -> km accuracy + * 1 -> m accuracy -- suitable for most mapping applications + * 2 -> mm accuracy + */ + iterations: 1, + + init : function() { + this.A = new Array(); + this.A[1] = +0.6399175073; + this.A[2] = -0.1358797613; + this.A[3] = +0.063294409; + this.A[4] = -0.02526853; + this.A[5] = +0.0117879; + this.A[6] = -0.0055161; + this.A[7] = +0.0026906; + this.A[8] = -0.001333; + this.A[9] = +0.00067; + this.A[10] = -0.00034; + + this.B_re = new Array(); this.B_im = new Array(); + this.B_re[1] = +0.7557853228; this.B_im[1] = 0.0; + this.B_re[2] = +0.249204646; this.B_im[2] = +0.003371507; + this.B_re[3] = -0.001541739; this.B_im[3] = +0.041058560; + this.B_re[4] = -0.10162907; this.B_im[4] = +0.01727609; + this.B_re[5] = -0.26623489; this.B_im[5] = -0.36249218; + this.B_re[6] = -0.6870983; this.B_im[6] = -1.1651967; + + this.C_re = new Array(); this.C_im = new Array(); + this.C_re[1] = +1.3231270439; this.C_im[1] = 0.0; + this.C_re[2] = -0.577245789; this.C_im[2] = -0.007809598; + this.C_re[3] = +0.508307513; this.C_im[3] = -0.112208952; + this.C_re[4] = -0.15094762; this.C_im[4] = +0.18200602; + this.C_re[5] = +1.01418179; this.C_im[5] = +1.64497696; + this.C_re[6] = +1.9660549; this.C_im[6] = +2.5127645; + + this.D = new Array(); + this.D[1] = +1.5627014243; + this.D[2] = +0.5185406398; + this.D[3] = -0.03333098; + this.D[4] = -0.1052906; + this.D[5] = -0.0368594; + this.D[6] = +0.007317; + this.D[7] = +0.01220; + this.D[8] = +0.00394; + this.D[9] = -0.0013; + }, + + /** + New Zealand Map Grid Forward - long/lat to x/y + long/lat in radians + */ + forward : function(p) { + var lon = p.x; + var lat = p.y; + + var delta_lat = lat - this.lat0; + var delta_lon = lon - this.long0; + + // 1. Calculate d_phi and d_psi ... // and d_lambda + // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians. + var d_phi = delta_lat / Proj4js.common.SEC_TO_RAD * 1E-5; var d_lambda = delta_lon; + var d_phi_n = 1; // d_phi^0 + + var d_psi = 0; + for (var n = 1; n <= 10; n++) { + d_phi_n = d_phi_n * d_phi; + d_psi = d_psi + this.A[n] * d_phi_n; + } + + // 2. Calculate theta + var th_re = d_psi; var th_im = d_lambda; + + // 3. Calculate z + var th_n_re = 1; var th_n_im = 0; // theta^0 + var th_n_re1; var th_n_im1; + + var z_re = 0; var z_im = 0; + for (var n = 1; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + z_re = z_re + this.B_re[n]*th_n_re - this.B_im[n]*th_n_im; z_im = z_im + this.B_im[n]*th_n_re + this.B_re[n]*th_n_im; + } + + // 4. Calculate easting and northing + p.x = (z_im * this.a) + this.x0; + p.y = (z_re * this.a) + this.y0; + + return p; + }, + + + /** + New Zealand Map Grid Inverse - x/y to long/lat + */ + inverse : function(p) { + + var x = p.x; + var y = p.y; + + var delta_x = x - this.x0; + var delta_y = y - this.y0; + + // 1. Calculate z + var z_re = delta_y / this.a; var z_im = delta_x / this.a; + + // 2a. Calculate theta - first approximation gives km accuracy + var z_n_re = 1; var z_n_im = 0; // z^0 + var z_n_re1; var z_n_im1; + + var th_re = 0; var th_im = 0; + for (var n = 1; n <= 6; n++) { + z_n_re1 = z_n_re*z_re - z_n_im*z_im; z_n_im1 = z_n_im*z_re + z_n_re*z_im; + z_n_re = z_n_re1; z_n_im = z_n_im1; + th_re = th_re + this.C_re[n]*z_n_re - this.C_im[n]*z_n_im; th_im = th_im + this.C_im[n]*z_n_re + this.C_re[n]*z_n_im; + } + + // 2b. Iterate to refine the accuracy of the calculation + // 0 iterations gives km accuracy + // 1 iteration gives m accuracy -- good enough for most mapping applications + // 2 iterations bives mm accuracy + for (var i = 0; i < this.iterations; i++) { + var th_n_re = th_re; var th_n_im = th_im; + var th_n_re1; var th_n_im1; + + var num_re = z_re; var num_im = z_im; + for (var n = 2; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + num_re = num_re + (n-1)*(this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); num_im = num_im + (n-1)*(this.B_im[n]*th_n_re + this.B_re[n]*th_n_im); + } + + th_n_re = 1; th_n_im = 0; + var den_re = this.B_re[1]; var den_im = this.B_im[1]; + for (var n = 2; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + den_re = den_re + n * (this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); den_im = den_im + n * (this.B_im[n]*th_n_re + this.B_re[n]*th_n_im); + } + + // Complex division + var den2 = den_re*den_re + den_im*den_im; + th_re = (num_re*den_re + num_im*den_im) / den2; th_im = (num_im*den_re - num_re*den_im) / den2; + } + + // 3. Calculate d_phi ... // and d_lambda + var d_psi = th_re; var d_lambda = th_im; + var d_psi_n = 1; // d_psi^0 + + var d_phi = 0; + for (var n = 1; n <= 9; n++) { + d_psi_n = d_psi_n * d_psi; + d_phi = d_phi + this.D[n] * d_psi_n; + } + + // 4. Calculate latitude and longitude + // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians. + var lat = this.lat0 + (d_phi * Proj4js.common.SEC_TO_RAD * 1E5); + var lon = this.long0 + d_lambda; + + p.x = lon; + p.y = lat; + + return p; + } +}; +/* ====================================================================== + projCode/mill.js + ====================================================================== */ + +/******************************************************************************* +NAME MILLER CYLINDRICAL + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Miller Cylindrical projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan March, 1993 + +This function was adapted from the Lambert Azimuthal Equal Area projection +code (FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. 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. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.mill = { + +/* Initialize the Miller Cylindrical projection + -------------------------------------------*/ + init: function() { + //no-op + }, + + + /* Miller Cylindrical forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ + forward: function(p) { + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + var dlon = Proj4js.common.adjust_lon(lon -this.long0); + var x = this.x0 + this.a * dlon; + var y = this.y0 + this.a * Math.log(Math.tan((Proj4js.common.PI / 4.0) + (lat / 2.5))) * 1.25; + + p.x=x; + p.y=y; + return p; + },//millFwd() + + /* Miller Cylindrical inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + + var lon = Proj4js.common.adjust_lon(this.long0 + p.x /this.a); + var lat = 2.5 * (Math.atan(Math.exp(0.8*p.y/this.a)) - Proj4js.common.PI / 4.0); + + p.x=lon; + p.y=lat; + return p; + }//millInv() +}; +/* ====================================================================== + projCode/gnom.js + ====================================================================== */ + +/***************************************************************************** +NAME GNOMONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Gnomonic Projection. + Implementation based on the existing sterea and ortho + implementations. + +PROGRAMMER DATE +---------- ---- +Richard Marsden November 2009 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map + Projections", University of Chicago Press 1993 + +2. Wolfram Mathworld "Gnomonic Projection" + http://mathworld.wolfram.com/GnomonicProjection.html + Accessed: 12th November 2009 +******************************************************************************/ + +Proj4js.Proj.gnom = { + + /* Initialize the Gnomonic projection + -------------------------------------*/ + init: function(def) { + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.sin_p14=Math.sin(this.lat0); + this.cos_p14=Math.cos(this.lat0); + // Approximation for projecting points to the horizon (infinity) + this.infinity_dist = 1000 * this.a; + this.rc = 1; + }, + + + /* Gnomonic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + forward: function(p) { + var sinphi, cosphi; /* sin and cos value */ + var dlon; /* delta longitude value */ + var coslon; /* cos of longitude */ + var ksp; /* scale factor */ + var g; + var x, y; + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + dlon = Proj4js.common.adjust_lon(lon - this.long0); + + sinphi=Math.sin(lat); + cosphi=Math.cos(lat); + + coslon = Math.cos(dlon); + g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; + ksp = 1.0; + if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) { + x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g; + y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g; + } else { + Proj4js.reportError("orthoFwdPointError"); + + // Point is in the opposing hemisphere and is unprojectable + // We still need to return a reasonable point, so we project + // to infinity, on a bearing + // equivalent to the northern hemisphere equivalent + // This is a reasonable approximation for short shapes and lines that + // straddle the horizon. + + x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon); + y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); + + } + p.x=x; + p.y=y; + return p; + }, + + + inverse: function(p) { + var rh; /* Rho */ + var z; /* angle */ + var sinc, cosc; + var c; + var lon , lat; + + /* Inverse equations + -----------------*/ + p.x = (p.x - this.x0) / this.a; + p.y = (p.y - this.y0) / this.a; + + p.x /= this.k0; + p.y /= this.k0; + + if ( (rh = Math.sqrt(p.x * p.x + p.y * p.y)) ) { + c = Math.atan2(rh, this.rc); + sinc = Math.sin(c); + cosc = Math.cos(c); + + lat = Proj4js.common.asinz(cosc*this.sin_p14 + (p.y*sinc*this.cos_p14) / rh); + lon = Math.atan2(p.x*sinc, rh*this.cos_p14*cosc - p.y*this.sin_p14*sinc); + lon = Proj4js.common.adjust_lon(this.long0+lon); + } else { + lat = this.phic0; + lon = 0.0; + } + + p.x=lon; + p.y=lat; + return p; + } +}; + + +/* ====================================================================== + projCode/sinu.js + ====================================================================== */ + +/******************************************************************************* +NAME SINUSOIDAL + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Sinusoidal projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS May, 1991 + +This function was adapted from the Sinusoidal projection code (FORTRAN) in the +General Cartographic Transformation Package software which is available from +the U.S. Geological Survey National Mapping Division. + +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. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.sinu = { + + /* Initialize the Sinusoidal projection + ------------------------------------*/ + init: function() { + /* Place parameters in static storage for common use + -------------------------------------------------*/ + + + if (!this.sphere) { + this.en = Proj4js.common.pj_enfn(this.es); + } else { + this.n = 1.; + this.m = 0.; + this.es = 0; + this.C_y = Math.sqrt((this.m + 1.) / this.n); + this.C_x = this.C_y/(this.m + 1.); + } + + }, + + /* Sinusoidal forward equations--mapping lat,long to x,y + -----------------------------------------------------*/ + forward: function(p) { + var x,y,delta_lon; + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + lon = Proj4js.common.adjust_lon(lon - this.long0); + + if (this.sphere) { + if (!this.m) { + lat = this.n != 1. ? Math.asin(this.n * Math.sin(lat)): lat; + } else { + var k = this.n * Math.sin(lat); + for (var i = Proj4js.common.MAX_ITER; i ; --i) { + var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat)); + lat -= V; + if (Math.abs(V) < Proj4js.common.EPSLN) break; + } + } + x = this.a * this.C_x * lon * (this.m + Math.cos(lat)); + y = this.a * this.C_y * lat; + + } else { + + var s = Math.sin(lat); + var c = Math.cos(lat); + y = this.a * Proj4js.common.pj_mlfn(lat, s, c, this.en); + x = this.a * lon * c / Math.sqrt(1. - this.es * s * s); + } + + p.x=x; + p.y=y; + return p; + }, + + inverse: function(p) { + var lat,temp,lon; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + lat = p.y / this.a; + + if (this.sphere) { + + p.y /= this.C_y; + lat = this.m ? Math.asin((this.m * p.y + Math.sin(p.y)) / this.n) : + ( this.n != 1. ? Math.asin(Math.sin(p.y) / this.n) : p.y ); + lon = p.x / (this.C_x * (this.m + Math.cos(p.y))); + + } else { + lat = Proj4js.common.pj_inv_mlfn(p.y/this.a, this.es, this.en) + var s = Math.abs(lat); + if (s < Proj4js.common.HALF_PI) { + s = Math.sin(lat); + temp = this.long0 + p.x * Math.sqrt(1. - this.es * s * s) /(this.a * Math.cos(lat)); + //temp = this.long0 + p.x / (this.a * Math.cos(lat)); + lon = Proj4js.common.adjust_lon(temp); + } else if ((s - Proj4js.common.EPSLN) < Proj4js.common.HALF_PI) { + lon = this.long0; + } + + } + + p.x=lon; + p.y=lat; + return p; + } +}; + + +/* ====================================================================== + projCode/vandg.js + ====================================================================== */ + +/******************************************************************************* +NAME VAN DER GRINTEN + +PURPOSE: Transforms input Easting and Northing to longitude and + latitude for the Van der Grinten projection. The + Easting and Northing must be in meters. The longitude + and latitude values will be returned in radians. + +PROGRAMMER DATE +---------- ---- +T. Mittan March, 1993 + +This function was adapted from the Van Der Grinten projection code +(FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. 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. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.vandg = { + +/* Initialize the Van Der Grinten projection + ----------------------------------------*/ + init: function() { + this.R = 6370997.0; //Radius of earth + }, + + forward: function(p) { + + var lon=p.x; + var lat=p.y; + + /* Forward equations + -----------------*/ + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var x,y; + + if (Math.abs(lat) <= Proj4js.common.EPSLN) { + x = this.x0 + this.R * dlon; + y = this.y0; + } + var theta = Proj4js.common.asinz(2.0 * Math.abs(lat / Proj4js.common.PI)); + if ((Math.abs(dlon) <= Proj4js.common.EPSLN) || (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) { + x = this.x0; + if (lat >= 0) { + y = this.y0 + Proj4js.common.PI * this.R * Math.tan(.5 * theta); + } else { + y = this.y0 + Proj4js.common.PI * this.R * - Math.tan(.5 * theta); + } + // return(OK); + } + var al = .5 * Math.abs((Proj4js.common.PI / dlon) - (dlon / Proj4js.common.PI)); + var asq = al * al; + var sinth = Math.sin(theta); + var costh = Math.cos(theta); + + var g = costh / (sinth + costh - 1.0); + var gsq = g * g; + var m = g * (2.0 / sinth - 1.0); + var msq = m * m; + var con = Proj4js.common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); + if (dlon < 0) { + con = -con; + } + x = this.x0 + con; + con = Math.abs(con / (Proj4js.common.PI * this.R)); + if (lat >= 0) { + y = this.y0 + Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); + } else { + y = this.y0 - Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); + } + p.x = x; + p.y = y; + return p; + }, + +/* Van Der Grinten inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ + inverse: function(p) { + var lon, lat; + var xx,yy,xys,c1,c2,c3; + var al,asq; + var a1; + var m1; + var con; + var th1; + var d; + + /* inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + con = Proj4js.common.PI * this.R; + xx = p.x / con; + yy =p.y / con; + xys = xx * xx + yy * yy; + c1 = -Math.abs(yy) * (1.0 + xys); + c2 = c1 - 2.0 * yy * yy + xx * xx; + c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys; + d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0; + a1 = (c1 - c2 * c2 / 3.0 / c3) / c3; + m1 = 2.0 * Math.sqrt( -a1 / 3.0); + con = ((3.0 * d) / a1) / m1; + if (Math.abs(con) > 1.0) { + if (con >= 0.0) { + con = 1.0; + } else { + con = -1.0; + } + } + th1 = Math.acos(con) / 3.0; + if (p.y >= 0) { + lat = (-m1 *Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI; + } else { + lat = -(-m1 * Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI; + } + + if (Math.abs(xx) < Proj4js.common.EPSLN) { + lon = this.long0; + } + lon = Proj4js.common.adjust_lon(this.long0 + Proj4js.common.PI * (xys - 1.0 + Math.sqrt(1.0 + 2.0 * (xx * xx - yy * yy) + xys * xys)) / 2.0 / xx); + + p.x=lon; + p.y=lat; + return p; + } +}; +/* ====================================================================== + projCode/cea.js + ====================================================================== */ + +/******************************************************************************* +NAME LAMBERT CYLINDRICAL EQUAL AREA + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Cylindrical Equal Area projection. + This class of projection includes the Behrmann and + Gall-Peters Projections. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +R. Marsden August 2009 +Winwaed Software Tech LLC, http://www.winwaed.com + +This function was adapted from the Miller Cylindrical Projection in the Proj4JS +library. + +Note: This implementation assumes a Spherical Earth. The (commented) code +has been included for the ellipsoidal forward transform, but derivation of +the ellispoidal inverse transform is beyond me. Note that most of the +Proj4JS implementations do NOT currently support ellipsoidal figures. +Therefore this is not seen as a problem - especially this lack of support +is explicitly stated here. + +ALGORITHM REFERENCES + +1. "Cartographic Projection Procedures for the UNIX Environment - + A User's Manual" by Gerald I. Evenden, USGS Open File Report 90-284 + and Release 4 Interim Reports (2003) + +2. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map + Projections", Univ. Chicago Press, 1993 +*******************************************************************************/ + +Proj4js.Proj.cea = { + +/* Initialize the Cylindrical Equal Area projection + -------------------------------------------*/ + init: function() { + //no-op + }, + + + /* Cylindrical Equal Area forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ + forward: function(p) { + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + var dlon = Proj4js.common.adjust_lon(lon -this.long0); + var x = this.x0 + this.a * dlon * Math.cos(this.lat_ts); + var y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts); + /* Elliptical Forward Transform + Not implemented due to a lack of a matchign inverse function + { + var Sin_Lat = Math.sin(lat); + var Rn = this.a * (Math.sqrt(1.0e0 - this.es * Sin_Lat * Sin_Lat )); + x = this.x0 + this.a * dlon * Math.cos(this.lat_ts); + y = this.y0 + Rn * Math.sin(lat) / Math.cos(this.lat_ts); + } + */ + + + p.x=x; + p.y=y; + return p; + },//ceaFwd() + + /* Cylindrical Equal Area inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + + var lon = Proj4js.common.adjust_lon( this.long0 + (p.x / this.a) / Math.cos(this.lat_ts) ); + + var lat = Math.asin( (p.y/this.a) * Math.cos(this.lat_ts) ); + + p.x=lon; + p.y=lat; + return p; + }//ceaInv() +}; +/* ====================================================================== + projCode/eqc.js + ====================================================================== */ + +/* similar to equi.js FIXME proj4 uses eqc */ +Proj4js.Proj.eqc = { + init : function() { + + if(!this.x0) this.x0=0; + if(!this.y0) this.y0=0; + if(!this.lat0) this.lat0=0; + if(!this.long0) this.long0=0; + if(!this.lat_ts) this.lat_ts=0; + if (!this.title) this.title = "Equidistant Cylindrical (Plate Carre)"; + + this.rc= Math.cos(this.lat_ts); + }, + + + // forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + forward : function(p) { + + var lon= p.x; + var lat= p.y; + + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var dlat = Proj4js.common.adjust_lat(lat - this.lat0 ); + p.x= this.x0 + (this.a*dlon*this.rc); + p.y= this.y0 + (this.a*dlat ); + return p; + }, + + // inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + inverse : function(p) { + + var x= p.x; + var y= p.y; + + p.x= Proj4js.common.adjust_lon(this.long0 + ((x - this.x0)/(this.a*this.rc))); + p.y= Proj4js.common.adjust_lat(this.lat0 + ((y - this.y0)/(this.a ))); + return p; + } + +}; +/* ====================================================================== + projCode/cass.js + ====================================================================== */ + +/******************************************************************************* +NAME CASSINI + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Cassini projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + Ported from PROJ.4. + + +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 +*******************************************************************************/ + + +//Proj4js.defs["EPSG:28191"] = "+proj=cass +lat_0=31.73409694444445 +lon_0=35.21208055555556 +x_0=170251.555 +y_0=126867.909 +a=6378300.789 +b=6356566.435 +towgs84=-275.722,94.7824,340.894,-8.001,-4.42,-11.821,1 +units=m +no_defs"; + +// Initialize the Cassini projection +// ----------------------------------------------------------------- + +Proj4js.Proj.cass = { + init : function() { + if (!this.sphere) { + this.en = Proj4js.common.pj_enfn(this.es) + this.m0 = Proj4js.common.pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en); + } + }, + + C1: .16666666666666666666, + C2: .00833333333333333333, + C3: .04166666666666666666, + C4: .33333333333333333333, + C5: .06666666666666666666, + + +/* Cassini forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ + forward: function(p) { + + /* Forward equations + -----------------*/ + var x,y; + var lam=p.x; + var phi=p.y; + lam = Proj4js.common.adjust_lon(lam - this.long0); + + if (this.sphere) { + x = Math.asin(Math.cos(phi) * Math.sin(lam)); + y = Math.atan2(Math.tan(phi) , Math.cos(lam)) - this.phi0; + } else { + //ellipsoid + this.n = Math.sin(phi); + this.c = Math.cos(phi); + y = Proj4js.common.pj_mlfn(phi, this.n, this.c, this.en); + this.n = 1./Math.sqrt(1. - this.es * this.n * this.n); + this.tn = Math.tan(phi); + this.t = this.tn * this.tn; + this.a1 = lam * this.c; + this.c *= this.es * this.c / (1 - this.es); + this.a2 = this.a1 * this.a1; + x = this.n * this.a1 * (1. - this.a2 * this.t * (this.C1 - (8. - this.t + 8. * this.c) * this.a2 * this.C2)); + y -= this.m0 - this.n * this.tn * this.a2 * (.5 + (5. - this.t + 6. * this.c) * this.a2 * this.C3); + } + + p.x = this.a*x + this.x0; + p.y = this.a*y + this.y0; + return p; + },//cassFwd() + +/* Inverse equations + -----------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + var x = p.x/this.a; + var y = p.y/this.a; + var phi, lam; + + if (this.sphere) { + this.dd = y + this.lat0; + phi = Math.asin(Math.sin(this.dd) * Math.cos(x)); + lam = Math.atan2(Math.tan(x), Math.cos(this.dd)); + } else { + /* ellipsoid */ + var ph1 = Proj4js.common.pj_inv_mlfn(this.m0 + y, this.es, this.en); + this.tn = Math.tan(ph1); + this.t = this.tn * this.tn; + this.n = Math.sin(ph1); + this.r = 1. / (1. - this.es * this.n * this.n); + this.n = Math.sqrt(this.r); + this.r *= (1. - this.es) * this.n; + this.dd = x / this.n; + this.d2 = this.dd * this.dd; + phi = ph1 - (this.n * this.tn / this.r) * this.d2 * (.5 - (1. + 3. * this.t) * this.d2 * this.C3); + lam = this.dd * (1. + this.t * this.d2 * (-this.C4 + (1. + 3. * this.t) * this.d2 * this.C5)) / Math.cos(ph1); + } + p.x = Proj4js.common.adjust_lon(this.long0+lam); + p.y = phi; + return p; + }//cassInv() + +} +/* ====================================================================== + projCode/gauss.js + ====================================================================== */ + + +Proj4js.Proj.gauss = { + + init : function() { + var sphi = Math.sin(this.lat0); + var 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; + var 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; + } +}; + +/* ====================================================================== + projCode/omerc.js + ====================================================================== */ + +/******************************************************************************* +NAME OBLIQUE MERCATOR (HOTINE) + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Oblique Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +Proj4js.Proj.omerc = { + + /* Initialize the Oblique Mercator projection + ------------------------------------------*/ + init: function() { + if (!this.mode) this.mode=0; + if (!this.lon1) {this.lon1=0;this.mode=1;} + if (!this.lon2) this.lon2=0; + if (!this.lat2) this.lat2=0; + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + var temp = this.b/ this.a; + var es = 1.0 - Math.pow(temp,2); + var e = Math.sqrt(es); + + this.sin_p20=Math.sin(this.lat0); + this.cos_p20=Math.cos(this.lat0); + + this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20; + this.com = Math.sqrt(1.0 - es); + this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es)); + this.al = this.a * this.bl * this.k0 * this.com / this.con; + if (Math.abs(this.lat0) < Proj4js.common.EPSLN) { + this.ts = 1.0; + this.d = 1.0; + this.el = 1.0; + } else { + this.ts = Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20); + this.con = Math.sqrt(this.con); + this.d = this.bl * this.com / (this.cos_p20 * this.con); + if ((this.d * this.d - 1.0) > 0.0) { + if (this.lat0 >= 0.0) { + this.f = this.d + Math.sqrt(this.d * this.d - 1.0); + } else { + this.f = this.d - Math.sqrt(this.d * this.d - 1.0); + } + } else { + this.f = this.d; + } + this.el = this.f * Math.pow(this.ts,this.bl); + } + + //this.longc=52.60353916666667; + + if (this.mode != 0) { + this.g = .5 * (this.f - 1.0/this.f); + this.gama = Proj4js.common.asinz(Math.sin(this.alpha) / this.d); + this.longc= this.longc - Proj4js.common.asinz(this.g * Math.tan(this.gama))/this.bl; + + /* Report parameters common to format B + -------------------------------------*/ + //genrpt(azimuth * R2D,"Azimuth of Central Line: "); + //cenlon(lon_origin); + // cenlat(lat_origin); + + this.con = Math.abs(this.lat0); + if ((this.con > Proj4js.common.EPSLN) && (Math.abs(this.con - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN)) { + this.singam=Math.sin(this.gama); + this.cosgam=Math.cos(this.gama); + + this.sinaz=Math.sin(this.alpha); + this.cosaz=Math.cos(this.alpha); + + if (this.lat0>= 0) { + this.u = (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz); + } else { + this.u = -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz); + } + } else { + Proj4js.reportError("omerc:Init:DataError"); + } + } else { + this.sinphi =Math. sin(this.at1); + this.ts1 = Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi); + this.sinphi = Math.sin(this.lat2); + this.ts2 = Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi); + this.h = Math.pow(this.ts1,this.bl); + this.l = Math.pow(this.ts2,this.bl); + this.f = this.el/this.h; + this.g = .5 * (this.f - 1.0/this.f); + this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h); + this.p = (this.l - this.h) / (this.l + this.h); + this.dlon = this.lon1 - this.lon2; + if (this.dlon < -Proj4js.common.PI) this.lon2 = this.lon2 - 2.0 * Proj4js.common.PI; + if (this.dlon > Proj4js.common.PI) this.lon2 = this.lon2 + 2.0 * Proj4js.common.PI; + this.dlon = this.lon1 - this.lon2; + this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl; + this.dlon = Proj4js.common.adjust_lon(this.lon1 - this.longc); + this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g); + this.alpha = Proj4js.common.asinz(this.d * Math.sin(this.gama)); + + /* Report parameters common to format A + -------------------------------------*/ + + if (Math.abs(this.lat1 - this.lat2) <= Proj4js.common.EPSLN) { + Proj4js.reportError("omercInitDataError"); + //return(202); + } else { + this.con = Math.abs(this.lat1); + } + if ((this.con <= Proj4js.common.EPSLN) || (Math.abs(this.con - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) { + Proj4js.reportError("omercInitDataError"); + //return(202); + } else { + if (Math.abs(Math.abs(this.lat0) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) { + Proj4js.reportError("omercInitDataError"); + //return(202); + } + } + + this.singam=Math.sin(this.gam); + this.cosgam=Math.cos(this.gam); + + this.sinaz=Math.sin(this.alpha); + this.cosaz=Math.cos(this.alpha); + + + if (this.lat0 >= 0) { + this.u = (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz); + } else { + this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz); + } + } + }, + + + /* Oblique Mercator forward equations--mapping lat,long to x,y + ----------------------------------------------------------*/ + forward: function(p) { + var theta; /* angle */ + var sin_phi, cos_phi;/* sin and cos value */ + var b; /* temporary values */ + var c, t, tq; /* temporary values */ + var con, n, ml; /* cone constant, small m */ + var q,us,vl; + var ul,vs; + var s; + var dlon; + var ts1; + + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + sin_phi = Math.sin(lat); + dlon = Proj4js.common.adjust_lon(lon - this.longc); + vl = Math.sin(this.bl * dlon); + if (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN) { + ts1 = Proj4js.common.tsfnz(this.e,lat,sin_phi); + q = this.el / (Math.pow(ts1,this.bl)); + s = .5 * (q - 1.0 / q); + t = .5 * (q + 1.0/ q); + ul = (s * this.singam - vl * this.cosgam) / t; + con = Math.cos(this.bl * dlon); + if (Math.abs(con) < .0000001) { + us = this.al * this.bl * dlon; + } else { + us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl; + if (con < 0) us = us + Proj4js.common.PI * this.al / this.bl; + } + } else { + if (lat >= 0) { + ul = this.singam; + } else { + ul = -this.singam; + } + us = this.al * lat / this.bl; + } + if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) { + //alert("Point projects into infinity","omer-for"); + Proj4js.reportError("omercFwdInfinity"); + //return(205); + } + vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl; + us = us - this.u; + var x = this.x0 + vs * this.cosaz + us * this.sinaz; + var y = this.y0 + us * this.cosaz - vs * this.sinaz; + + p.x=x; + p.y=y; + return p; + }, + + inverse: function(p) { + var delta_lon; /* Delta longitude (Given longitude - center */ + var theta; /* angle */ + var delta_theta; /* adjusted longitude */ + var sin_phi, cos_phi;/* sin and cos value */ + var b; /* temporary values */ + var c, t, tq; /* temporary values */ + var con, n, ml; /* cone constant, small m */ + var vs,us,q,s,ts1; + var vl,ul,bs; + var lon, lat; + var flag; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + flag = 0; + vs = p.x * this.cosaz - p.y * this.sinaz; + us = p.y * this.cosaz + p.x * this.sinaz; + us = us + this.u; + q = Math.exp(-this.bl * vs / this.al); + s = .5 * (q - 1.0/q); + t = .5 * (q + 1.0/q); + vl = Math.sin(this.bl * us / this.al); + ul = (vl * this.cosgam + s * this.singam)/t; + if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) + { + lon = this.longc; + if (ul >= 0.0) { + lat = Proj4js.common.HALF_PI; + } else { + lat = -Proj4js.common.HALF_PI; + } + } else { + con = 1.0 / this.bl; + ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con); + lat = Proj4js.common.phi2z(this.e,ts1); + //if (flag != 0) + //return(flag); + //~ con = Math.cos(this.bl * us /al); + theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl; + lon = Proj4js.common.adjust_lon(theta); + } + p.x=lon; + p.y=lat; + return p; + } +}; +/* ====================================================================== + projCode/lcc.js + ====================================================================== */ + +/******************************************************************************* +NAME LAMBERT CONFORMAL CONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Conformal Conic 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 +*******************************************************************************/ + + +//<2104> +proj=lcc +lat_1=10.16666666666667 +lat_0=10.16666666666667 +lon_0=-71.60561777777777 +k_0=1 +x0=-17044 +x0=-23139.97 +ellps=intl +units=m +no_defs no_defs + +// Initialize the Lambert Conformal conic projection +// ----------------------------------------------------------------- + +//Proj4js.Proj.lcc = Class.create(); +Proj4js.Proj.lcc = { + init : function() { + + // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north + //double c_lat; /* center latitude */ + //double c_lon; /* center longitude */ + //double lat1; /* first standard parallel */ + //double lat2; /* second standard parallel */ + //double r_maj; /* major axis */ + //double r_min; /* minor axis */ + //double false_east; /* x offset in meters */ + //double false_north; /* y offset in meters */ + + if (!this.lat2){this.lat2=this.lat0;}//if lat2 is not defined + if (!this.k0) this.k0 = 1.0; + + // Standard Parallels cannot be equal and on opposite sides of the equator + if (Math.abs(this.lat1+this.lat2) < Proj4js.common.EPSLN) { + Proj4js.reportError("lcc:init: Equal Latitudes"); + return; + } + + var temp = this.b / this.a; + this.e = Math.sqrt(1.0 - temp*temp); + + var sin1 = Math.sin(this.lat1); + var cos1 = Math.cos(this.lat1); + var ms1 = Proj4js.common.msfnz(this.e, sin1, cos1); + var ts1 = Proj4js.common.tsfnz(this.e, this.lat1, sin1); + + var sin2 = Math.sin(this.lat2); + var cos2 = Math.cos(this.lat2); + var ms2 = Proj4js.common.msfnz(this.e, sin2, cos2); + var ts2 = Proj4js.common.tsfnz(this.e, this.lat2, sin2); + + var ts0 = Proj4js.common.tsfnz(this.e, this.lat0, Math.sin(this.lat0)); + + if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) { + this.ns = Math.log(ms1/ms2)/Math.log(ts1/ts2); + } else { + this.ns = sin1; + } + this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns)); + this.rh = this.a * this.f0 * Math.pow(ts0, this.ns); + if (!this.title) this.title = "Lambert Conformal Conic"; + }, + + + // Lambert Conformal conic forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + forward : function(p) { + + var lon = p.x; + var lat = p.y; + + // convert to radians + if ( lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0) { + //lon = lon * Proj4js.common.D2R; + //lat = lat * Proj4js.common.D2R; + } else { + Proj4js.reportError("lcc:forward: llInputOutOfRange: "+ lon +" : " + lat); + return null; + } + + var con = Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI); + var ts, rh1; + if (con > Proj4js.common.EPSLN) { + ts = Proj4js.common.tsfnz(this.e, lat, Math.sin(lat) ); + rh1 = this.a * this.f0 * Math.pow(ts, this.ns); + } else { + con = lat * this.ns; + if (con <= 0) { + Proj4js.reportError("lcc:forward: No Projection"); + return null; + } + rh1 = 0; + } + var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0); + p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0; + p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0; + + return p; + }, + + // Lambert Conformal Conic inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + inverse : function(p) { + + var rh1, con, ts; + var lat, lon; + var x = (p.x - this.x0)/this.k0; + var y = (this.rh - (p.y - this.y0)/this.k0); + if (this.ns > 0) { + rh1 = Math.sqrt (x * x + y * y); + con = 1.0; + } else { + rh1 = -Math.sqrt (x * x + y * y); + con = -1.0; + } + var theta = 0.0; + if (rh1 != 0) { + theta = Math.atan2((con * x),(con * y)); + } + if ((rh1 != 0) || (this.ns > 0.0)) { + con = 1.0/this.ns; + ts = Math.pow((rh1/(this.a * this.f0)), con); + lat = Proj4js.common.phi2z(this.e, ts); + if (lat == -9999) return null; + } else { + lat = -Proj4js.common.HALF_PI; + } + lon = Proj4js.common.adjust_lon(theta/this.ns + this.long0); + + p.x = lon; + p.y = lat; + return p; + } +}; + + + + +/* ====================================================================== + projCode/laea.js + ====================================================================== */ + +/******************************************************************************* +NAME LAMBERT AZIMUTHAL EQUAL-AREA + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Azimuthal Equal-Area projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS March, 1991 + +This function was adapted from the Lambert Azimuthal Equal Area projection +code (FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. 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. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.laea = { + S_POLE: 1, + N_POLE: 2, + EQUIT: 3, + OBLIQ: 4, + + +/* Initialize the Lambert Azimuthal Equal Area projection + ------------------------------------------------------*/ + init: function() { + var t = Math.abs(this.lat0); + if (Math.abs(t - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) { + this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE; + } else if (Math.abs(t) < Proj4js.common.EPSLN) { + this.mode = this.EQUIT; + } else { + this.mode = this.OBLIQ; + } + if (this.es > 0) { + var sinphi; + + this.qp = Proj4js.common.qsfnz(this.e, 1.0); + this.mmf = .5 / (1. - this.es); + this.apa = this.authset(this.es); + switch (this.mode) { + case this.N_POLE: + case this.S_POLE: + this.dd = 1.; + break; + case this.EQUIT: + this.rq = Math.sqrt(.5 * this.qp); + this.dd = 1. / this.rq; + this.xmf = 1.; + this.ymf = .5 * this.qp; + break; + case this.OBLIQ: + this.rq = Math.sqrt(.5 * this.qp); + sinphi = Math.sin(this.lat0); + this.sinb1 = Proj4js.common.qsfnz(this.e, sinphi) / this.qp; + this.cosb1 = Math.sqrt(1. - this.sinb1 * this.sinb1); + this.dd = Math.cos(this.lat0) / (Math.sqrt(1. - this.es * sinphi * sinphi) * this.rq * this.cosb1); + this.ymf = (this.xmf = this.rq) / this.dd; + this.xmf *= this.dd; + break; + } + } else { + if (this.mode == this.OBLIQ) { + this.sinph0 = Math.sin(this.lat0); + this.cosph0 = Math.cos(this.lat0); + } + } + }, + +/* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ + forward: function(p) { + + /* Forward equations + -----------------*/ + var x,y; + var lam=p.x; + var phi=p.y; + lam = Proj4js.common.adjust_lon(lam - this.long0); + + if (this.sphere) { + var coslam, cosphi, sinphi; + + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + coslam = Math.cos(lam); + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + y = (this.mode == this.EQUIT) ? 1. + cosphi * coslam : 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam; + if (y <= Proj4js.common.EPSLN) { + Proj4js.reportError("laea:fwd:y less than eps"); + return null; + } + y = Math.sqrt(2. / y); + x = y * cosphi * Math.sin(lam); + y *= (this.mode == this.EQUIT) ? sinphi : this.cosph0 * sinphi - this.sinph0 * cosphi * coslam; + break; + case this.N_POLE: + coslam = -coslam; + case this.S_POLE: + if (Math.abs(phi + this.phi0) < Proj4js.common.EPSLN) { + Proj4js.reportError("laea:fwd:phi < eps"); + return null; + } + y = Proj4js.common.FORTPI - phi * .5; + y = 2. * ((this.mode == this.S_POLE) ? Math.cos(y) : Math.sin(y)); + x = y * Math.sin(lam); + y *= coslam; + break; + } + } else { + var coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; + + coslam = Math.cos(lam); + sinlam = Math.sin(lam); + sinphi = Math.sin(phi); + q = Proj4js.common.qsfnz(this.e, sinphi); + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + sinb = q / this.qp; + cosb = Math.sqrt(1. - sinb * sinb); + } + switch (this.mode) { + case this.OBLIQ: + b = 1. + this.sinb1 * sinb + this.cosb1 * cosb * coslam; + break; + case this.EQUIT: + b = 1. + cosb * coslam; + break; + case this.N_POLE: + b = Proj4js.common.HALF_PI + phi; + q = this.qp - q; + break; + case this.S_POLE: + b = phi - Proj4js.common.HALF_PI; + q = this.qp + q; + break; + } + if (Math.abs(b) < Proj4js.common.EPSLN) { + Proj4js.reportError("laea:fwd:b < eps"); + return null; + } + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + b = Math.sqrt(2. / b); + if (this.mode == this.OBLIQ) { + y = this.ymf * b * (this.cosb1 * sinb - this.sinb1 * cosb * coslam); + } else { + y = (b = Math.sqrt(2. / (1. + cosb * coslam))) * sinb * this.ymf; + } + x = this.xmf * b * cosb * sinlam; + break; + case this.N_POLE: + case this.S_POLE: + if (q >= 0.) { + x = (b = Math.sqrt(q)) * sinlam; + y = coslam * ((this.mode == this.S_POLE) ? b : -b); + } else { + x = y = 0.; + } + break; + } + } + + //v 1.0 + /* + var sin_lat=Math.sin(lat); + var cos_lat=Math.cos(lat); + + var sin_delta_lon=Math.sin(delta_lon); + var cos_delta_lon=Math.cos(delta_lon); + + var g =this.sin_lat_o * sin_lat +this.cos_lat_o * cos_lat * cos_delta_lon; + if (g == -1.0) { + Proj4js.reportError("laea:fwd:Point projects to a circle of radius "+ 2.0 * R); + return null; + } + var ksp = this.a * Math.sqrt(2.0 / (1.0 + g)); + var x = ksp * cos_lat * sin_delta_lon + this.x0; + var y = ksp * (this.cos_lat_o * sin_lat - this.sin_lat_o * cos_lat * cos_delta_lon) + this.y0; + */ + p.x = this.a*x + this.x0; + p.y = this.a*y + this.y0; + return p; + },//lamazFwd() + +/* Inverse equations + -----------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + var x = p.x/this.a; + var y = p.y/this.a; + var lam, phi; + + if (this.sphere) { + var cosz=0.0, rh, sinz=0.0; + + rh = Math.sqrt(x*x + y*y); + phi = rh * .5; + if (phi > 1.) { + Proj4js.reportError("laea:Inv:DataError"); + return null; + } + phi = 2. * Math.asin(phi); + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + sinz = Math.sin(phi); + cosz = Math.cos(phi); + } + switch (this.mode) { + case this.EQUIT: + phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? 0. : Math.asin(y * sinz / rh); + x *= sinz; + y = cosz * rh; + break; + case this.OBLIQ: + phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? this.phi0 : Math.asin(cosz * this.sinph0 + y * sinz * this.cosph0 / rh); + x *= sinz * this.cosph0; + y = (cosz - Math.sin(phi) * this.sinph0) * rh; + break; + case this.N_POLE: + y = -y; + phi = Proj4js.common.HALF_PI - phi; + break; + case this.S_POLE: + phi -= Proj4js.common.HALF_PI; + break; + } + lam = (y == 0. && (this.mode == this.EQUIT || this.mode == this.OBLIQ)) ? 0. : Math.atan2(x, y); + } else { + var cCe, sCe, q, rho, ab=0.0; + + switch (this.mode) { + case this.EQUIT: + case this.OBLIQ: + x /= this.dd; + y *= this.dd; + rho = Math.sqrt(x*x + y*y); + if (rho < Proj4js.common.EPSLN) { + p.x = 0.; + p.y = this.phi0; + return p; + } + sCe = 2. * Math.asin(.5 * rho / this.rq); + cCe = Math.cos(sCe); + x *= (sCe = Math.sin(sCe)); + if (this.mode == this.OBLIQ) { + ab = cCe * this.sinb1 + y * sCe * this.cosb1 / rho + q = this.qp * ab; + y = rho * this.cosb1 * cCe - y * this.sinb1 * sCe; + } else { + ab = y * sCe / rho; + q = this.qp * ab; + y = rho * cCe; + } + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + q = (x * x + y * y); + if (!q ) { + p.x = 0.; + p.y = this.phi0; + return p; + } + /* + q = this.qp - q; + */ + ab = 1. - q / this.qp; + if (this.mode == this.S_POLE) { + ab = - ab; + } + break; + } + lam = Math.atan2(x, y); + phi = this.authlat(Math.asin(ab), this.apa); + } + + /* + var Rh = Math.Math.sqrt(p.x *p.x +p.y * p.y); + var temp = Rh / (2.0 * this.a); + + if (temp > 1) { + Proj4js.reportError("laea:Inv:DataError"); + return null; + } + + var z = 2.0 * Proj4js.common.asinz(temp); + var sin_z=Math.sin(z); + var cos_z=Math.cos(z); + + var lon =this.long0; + if (Math.abs(Rh) > Proj4js.common.EPSLN) { + var lat = Proj4js.common.asinz(this.sin_lat_o * cos_z +this. cos_lat_o * sin_z *p.y / Rh); + var temp =Math.abs(this.lat0) - Proj4js.common.HALF_PI; + if (Math.abs(temp) > Proj4js.common.EPSLN) { + temp = cos_z -this.sin_lat_o * Math.sin(lat); + if(temp!=0.0) lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh)); + } else if (this.lat0 < 0.0) { + lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x,p.y)); + } else { + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y)); + } + } else { + lat = this.lat0; + } + */ + //return(OK); + p.x = Proj4js.common.adjust_lon(this.long0+lam); + p.y = phi; + return p; + },//lamazInv() + +/* determine latitude from authalic latitude */ + P00: .33333333333333333333, + P01: .17222222222222222222, + P02: .10257936507936507936, + P10: .06388888888888888888, + P11: .06640211640211640211, + P20: .01641501294219154443, + + authset: function(es) { + var t; + var APA = new Array(); + APA[0] = es * this.P00; + t = es * es; + APA[0] += t * this.P01; + APA[1] = t * this.P10; + t *= es; + APA[0] += t * this.P02; + APA[1] += t * this.P11; + APA[2] = t * this.P20; + return APA; + }, + + authlat: function(beta, APA) { + var t = beta+beta; + return(beta + APA[0] * Math.sin(t) + APA[1] * Math.sin(t+t) + APA[2] * Math.sin(t+t+t)); + } + +}; + + + +/* ====================================================================== + projCode/aeqd.js + ====================================================================== */ + +Proj4js.Proj.aeqd = { + + init : function() { + this.sin_p12=Math.sin(this.lat0); + this.cos_p12=Math.cos(this.lat0); + }, + + forward: function(p) { + var lon=p.x; + var lat=p.y; + var ksp; + + var sinphi=Math.sin(p.y); + var cosphi=Math.cos(p.y); + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var coslon = Math.cos(dlon); + var g = this.sin_p12 * sinphi + this.cos_p12 * cosphi * coslon; + if (Math.abs(Math.abs(g) - 1.0) < Proj4js.common.EPSLN) { + ksp = 1.0; + if (g < 0.0) { + Proj4js.reportError("aeqd:Fwd:PointError"); + return; + } + } else { + var z = Math.acos(g); + ksp = z/Math.sin(z); + } + p.x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon); + p.y = this.y0 + this.a * ksp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * coslon); + return p; + }, + + inverse: function(p){ + p.x -= this.x0; + p.y -= this.y0; + + var rh = Math.sqrt(p.x * p.x + p.y *p.y); + if (rh > (2.0 * Proj4js.common.HALF_PI * this.a)) { + Proj4js.reportError("aeqdInvDataError"); + return; + } + var z = rh / this.a; + + var sinz=Math.sin(z); + var cosz=Math.cos(z); + + var lon = this.long0; + var lat; + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.lat0; + } else { + lat = Proj4js.common.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh); + var con = Math.abs(this.lat0) - Proj4js.common.HALF_PI; + if (Math.abs(con) <= Proj4js.common.EPSLN) { + if (this.lat0 >= 0.0) { + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x , -p.y)); + } else { + lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x , p.y)); + } + } else { + con = cosz - this.sin_p12 * Math.sin(lat); + if ((Math.abs(con) < Proj4js.common.EPSLN) && (Math.abs(p.x) < Proj4js.common.EPSLN)) { + //no-op, just keep the lon value as is + } else { + var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh)); + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh))); + } + } + } + + p.x = lon; + p.y = lat; + return p; + } +}; +/* ====================================================================== + projCode/moll.js + ====================================================================== */ + +/******************************************************************************* +NAME MOLLWEIDE + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the MOllweide projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS May, 1991; Updated Sept, 1992; Updated Feb, 1993 +S. Nelson, EDC Jun, 2993; Made corrections in precision and + number of iterations. + +ALGORITHM REFERENCES + +1. 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. + +2. 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. +*******************************************************************************/ + +Proj4js.Proj.moll = { + + /* Initialize the Mollweide projection + ------------------------------------*/ + init: function(){ + //no-op + }, + + /* Mollweide forward equations--mapping lat,long to x,y + ----------------------------------------------------*/ + forward: function(p) { + + /* Forward equations + -----------------*/ + var lon=p.x; + var lat=p.y; + + var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); + var theta = lat; + var con = Proj4js.common.PI * Math.sin(lat); + + /* Iterate using the Newton-Raphson method to find theta + -----------------------------------------------------*/ + for (var i=0;true;i++) { + var delta_theta = -(theta + Math.sin(theta) - con)/ (1.0 + Math.cos(theta)); + theta += delta_theta; + if (Math.abs(delta_theta) < Proj4js.common.EPSLN) break; + if (i >= 50) { + Proj4js.reportError("moll:Fwd:IterationError"); + //return(241); + } + } + theta /= 2.0; + + /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting" + this is done here because of precision problems with "cos(theta)" + --------------------------------------------------------------------------*/ + if (Proj4js.common.PI/2 - Math.abs(lat) < Proj4js.common.EPSLN) delta_lon =0; + var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0; + var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0; + + p.x=x; + p.y=y; + return p; + }, + + inverse: function(p){ + var theta; + var arg; + + /* Inverse equations + -----------------*/ + p.x-= this.x0; + //~ p.y -= this.y0; + var arg = p.y / (1.4142135623731 * this.a); + + /* Because of division by zero problems, 'arg' can not be 1.0. Therefore + a number very close to one is used instead. + -------------------------------------------------------------------*/ + if(Math.abs(arg) > 0.999999999999) arg=0.999999999999; + var theta =Math.asin(arg); + var lon = Proj4js.common.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta)))); + if(lon < (-Proj4js.common.PI)) lon= -Proj4js.common.PI; + if(lon > Proj4js.common.PI) lon= Proj4js.common.PI; + arg = (2.0 * theta + Math.sin(2.0 * theta)) / Proj4js.common.PI; + if(Math.abs(arg) > 1.0)arg=1.0; + var lat = Math.asin(arg); + //return(OK); + + p.x=lon; + p.y=lat; + return p; + } +}; + diff --git a/src/main/webapp/com/plugins/proj4js/proj4js-compressed.js b/src/main/webapp/com/plugins/proj4js/proj4js-compressed.js new file mode 100644 index 0000000..a55fa5a --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/proj4js-compressed.js @@ -0,0 +1,180 @@ +/* + proj4js.js -- Javascript reprojection library. + + Authors: Mike Adair madairATdmsolutions.ca + Richard Greenwood richATgreenwoodmap.com + Didier Richard didier.richardATign.fr + Stephen Irons stephen.ironsATclear.net.nz + Olivier Terral oterralATgmail.com + + License: + Copyright (c) 2012, Mike Adair, Richard Greenwood, Didier Richard, + Stephen Irons and Olivier Terral + + 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. + + Note: This program is an almost direct port of the C library PROJ.4. +*/ +var Proj4js={defaultDatum:"WGS84",transform:function(a,c,b){if(!a.readyToUse)return this.reportError("Proj4js initialization for:"+a.srsCode+" not yet complete"),b;if(!c.readyToUse)return this.reportError("Proj4js initialization for:"+c.srsCode+" not yet complete"),b;if(a.datum&&c.datum&&((a.datum.datum_type==Proj4js.common.PJD_3PARAM||a.datum.datum_type==Proj4js.common.PJD_7PARAM)&&"WGS84"!=c.datumCode||(c.datum.datum_type==Proj4js.common.PJD_3PARAM||c.datum.datum_type==Proj4js.common.PJD_7PARAM)&& +"WGS84"!=a.datumCode)){var d=Proj4js.WGS84;this.transform(a,d,b);a=d}"enu"!=a.axis&&this.adjust_axis(a,!1,b);"longlat"==a.projName?(b.x*=Proj4js.common.D2R,b.y*=Proj4js.common.D2R):(a.to_meter&&(b.x*=a.to_meter,b.y*=a.to_meter),a.inverse(b));a.from_greenwich&&(b.x+=a.from_greenwich);b=this.datum_transform(a.datum,c.datum,b);c.from_greenwich&&(b.x-=c.from_greenwich);"longlat"==c.projName?(b.x*=Proj4js.common.R2D,b.y*=Proj4js.common.R2D):(c.forward(b),c.to_meter&&(b.x/=c.to_meter,b.y/=c.to_meter)); +"enu"!=c.axis&&this.adjust_axis(c,!0,b);return b},datum_transform:function(a,c,b){if(a.compare_datums(c)||a.datum_type==Proj4js.common.PJD_NODATUM||c.datum_type==Proj4js.common.PJD_NODATUM)return b;if(a.es!=c.es||a.a!=c.a||a.datum_type==Proj4js.common.PJD_3PARAM||a.datum_type==Proj4js.common.PJD_7PARAM||c.datum_type==Proj4js.common.PJD_3PARAM||c.datum_type==Proj4js.common.PJD_7PARAM)a.geodetic_to_geocentric(b),(a.datum_type==Proj4js.common.PJD_3PARAM||a.datum_type==Proj4js.common.PJD_7PARAM)&&a.geocentric_to_wgs84(b), +(c.datum_type==Proj4js.common.PJD_3PARAM||c.datum_type==Proj4js.common.PJD_7PARAM)&&c.geocentric_from_wgs84(b),c.geocentric_to_geodetic(b);return b},adjust_axis:function(a,c,b){for(var d=b.x,e=b.y,f=b.z||0,g,i,h=0;3>h;h++)if(!c||!(2==h&&void 0===b.z))switch(0==h?(g=d,i="x"):1==h?(g=e,i="y"):(g=f,i="z"),a.axis[h]){case "e":b[i]=g;break;case "w":b[i]=-g;break;case "n":b[i]=g;break;case "s":b[i]=-g;break;case "u":void 0!==b[i]&&(b.z=g);break;case "d":void 0!==b[i]&&(b.z=-g);break;default:return alert("ERROR: unknow axis ("+ +a.axis[h]+") - check definition of "+a.projName),null}return b},reportError:function(){},extend:function(a,c){a=a||{};if(c)for(var b in c){var d=c[b];void 0!==d&&(a[b]=d)}return a},Class:function(){for(var a=function(){this.initialize.apply(this,arguments)},c={},b,d=0;d=f;f++)if(d=a*Math.sin(e),d=this.HALF_PI-2*Math.atan(c*Math.pow((1-d)/(1+d),b))-e,e+=d,1.0E-10>=Math.abs(d))return e;alert("phi2z has NoConvergence");return-9999},qsfnz:function(a,c){var b;return 1.0E-7a?-1:1},adjust_lon:function(a){return a=Math.abs(a)this.HALF_PI)return+Number.NaN;if(c==this.HALF_PI)return Number.POSITIVE_INFINITY;if(c==-1*this.HALF_PI)return-1*Number.POSITIVE_INFINITY;b*=a;return Math.log(Math.tan((this.HALF_PI+c)/2))+a*Math.log((1-b)/(1+b))/2},fL:function(a,c){return 2*Math.atan(a*Math.exp(c))-this.HALF_PI},invlatiso:function(a,c){var b=this.fL(1,c),d=0,e=0;do d=b,e=a*Math.sin(d),b=this.fL(Math.exp(a*Math.log((1+e)/(1-e))/2),c);while(1.0E-12< +Math.abs(b-d));return b},sinh:function(a){a=Math.exp(a);return(a-1/a)/2},cosh:function(a){a=Math.exp(a);return(a+1/a)/2},tanh:function(a){a=Math.exp(a);return(a-1/a)/(a+1/a)},asinh:function(a){return(0<=a?1:-1)*Math.log(Math.abs(a)+Math.sqrt(a*a+1))},acosh:function(a){return 2*Math.log(Math.sqrt((a+1)/2)+Math.sqrt((a-1)/2))},atanh:function(a){return Math.log((a-1)/(a+1))/2},gN:function(a,c,b){c*=b;return a/Math.sqrt(1-c*c)},pj_enfn:function(a){var c=[];c[0]=this.C00-a*(this.C02+a*(this.C04+a*(this.C06+ +a*this.C08)));c[1]=a*(this.C22-a*(this.C04+a*(this.C06+a*this.C08)));var b=a*a;c[2]=b*(this.C44-a*(this.C46+a*this.C48));b*=a;c[3]=b*(this.C66-a*this.C68);c[4]=b*a*this.C88;return c},pj_mlfn:function(a,c,b,d){b*=c;c*=c;return d[0]*a-b*(d[1]+c*(d[2]+c*(d[3]+c*d[4])))},pj_inv_mlfn:function(a,c,b){for(var d=1/(1-c),e=a,f=Proj4js.common.MAX_ITER;f;--f){var g=Math.sin(e),i=1-c*g*g,i=(this.pj_mlfn(e,g,Math.cos(e),b)-a)*i*Math.sqrt(i)*d,e=e-i;if(Math.abs(i)-1.001*Proj4js.common.HALF_PI)b=-Proj4js.common.HALF_PI;else if(b>Proj4js.common.HALF_PI&&b<1.001*Proj4js.common.HALF_PI)b=Proj4js.common.HALF_PI;else if(b<-Proj4js.common.HALF_PI||b>Proj4js.common.HALF_PI)return Proj4js.reportError("geocent:lat out of range:"+b),null;c>Proj4js.common.PI&&(c-=2*Proj4js.common.PI);f=Math.sin(b);g=Math.cos(b);e=this.a/Math.sqrt(1-this.es*f*f);b=(e+d)*g*Math.cos(c); +c=(e+d)*g*Math.sin(c);d=(e*(1-this.es)+d)*f;a.x=b;a.y=c;a.z=d;return 0},geocentric_to_geodetic:function(a){var c,b,d,e,f,g,i,h,j,k,l=a.x;d=a.y;var m=a.z?a.z:0;c=Math.sqrt(l*l+d*d);b=Math.sqrt(l*l+d*d+m*m);if(1.0E-12>c/this.a){if(l=0,1.0E-12>b/this.a)return}else l=Math.atan2(d,l);d=m/b;e=c/b;f=1/Math.sqrt(1-this.es*(2-this.es)*e*e);i=e*(1-this.es)*f;h=d*f;k=0;do k++,g=this.a/Math.sqrt(1-this.es*h*h),b=c*i+m*h-g*(1-this.es*h*h),g=this.es*g/(g+b),f=1/Math.sqrt(1-g*(2-g)*e*e),g=e*(1-g)*f,f*=d,j=f*i-g* +h,i=g,h=f;while(1.0E-24k);c=Math.atan(f/Math.abs(g));a.x=l;a.y=c;a.z=b;return a},geocentric_to_geodetic_noniter:function(a){var c=a.x,b=a.y,d=a.z?a.z:0,e,f,g,i,h,c=parseFloat(c),b=parseFloat(b),d=parseFloat(d);h=!1;if(0!=c)e=Math.atan2(b,c);else if(0b)e=-Proj4js.common.HALF_PI;else if(h=!0,e=0,0d)f=-Proj4js.common.HALF_PI;else return;g=c*c+b*b;c=Math.sqrt(g);b=d*Proj4js.common.AD_C;g=Math.sqrt(b*b+g);b/=g;g=c/g;b= +d+this.b*this.ep2*b*b*b;i=c-this.a*this.es*g*g*g;g=Math.sqrt(b*b+i*i);b/=g;g=i/g;i=this.a/Math.sqrt(1-this.es*b*b);d=g>=Proj4js.common.COS_67P5?c/g-i:g<=-Proj4js.common.COS_67P5?c/-g-i:d/b+i*(this.es-1);!1==h&&(f=Math.atan(b/g));a.x=e;a.y=f;a.z=d;return a},geocentric_to_wgs84:function(a){if(this.datum_type==Proj4js.common.PJD_3PARAM)a.x+=this.datum_params[0],a.y+=this.datum_params[1],a.z+=this.datum_params[2];else if(this.datum_type==Proj4js.common.PJD_7PARAM){var c=this.datum_params[3],b=this.datum_params[4], +d=this.datum_params[5],e=this.datum_params[6],f=e*(d*a.x+a.y-c*a.z)+this.datum_params[1],c=e*(-b*a.x+c*a.y+a.z)+this.datum_params[2];a.x=e*(a.x-d*a.y+b*a.z)+this.datum_params[0];a.y=f;a.z=c}},geocentric_from_wgs84:function(a){if(this.datum_type==Proj4js.common.PJD_3PARAM)a.x-=this.datum_params[0],a.y-=this.datum_params[1],a.z-=this.datum_params[2];else if(this.datum_type==Proj4js.common.PJD_7PARAM){var c=this.datum_params[3],b=this.datum_params[4],d=this.datum_params[5],e=this.datum_params[6],f=(a.x- +this.datum_params[0])/e,g=(a.y-this.datum_params[1])/e,e=(a.z-this.datum_params[2])/e;a.x=f+d*g-b*e;a.y=-d*f+g+c*e;a.z=b*f-c*g+e}}}); +Proj4js.Point=Proj4js.Class({initialize:function(a,c,b){"object"==typeof a?(this.x=a[0],this.y=a[1],this.z=a[2]||0):"string"==typeof a&&"undefined"==typeof c?(a=a.split(","),this.x=parseFloat(a[0]),this.y=parseFloat(a[1]),this.z=parseFloat(a[2])||0):(this.x=a,this.y=c,this.z=b||0)},clone:function(){return new Proj4js.Point(this.x,this.y,this.z)},toString:function(){return"x="+this.x+",y="+this.y},toShortString:function(){return this.x+", "+this.y}}); +Proj4js.PrimeMeridian={greenwich:0,lisbon:-9.131906111111,paris:2.337229166667,bogota:-74.080916666667,madrid:-3.687938888889,rome:12.452333333333,bern:7.439583333333,jakarta:106.807719444444,ferro:-17.666666666667,brussels:4.367975,stockholm:18.058277777778,athens:23.7163375,oslo:10.722916666667}; +Proj4js.Ellipsoid={MERIT:{a:6378137,rf:298.257,ellipseName:"MERIT 1983"},SGS85:{a:6378136,rf:298.257,ellipseName:"Soviet Geodetic System 85"},GRS80:{a:6378137,rf:298.257222101,ellipseName:"GRS 1980(IUGG, 1980)"},IAU76:{a:6378140,rf:298.257,ellipseName:"IAU 1976"},airy:{a:6377563.396,b:6356256.91,ellipseName:"Airy 1830"},"APL4.":{a:6378137,rf:298.25,ellipseName:"Appl. Physics. 1965"},NWL9D:{a:6378145,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,ellipseName:"Andrae 1876 (Den., Iclnd.)"},aust_SA:{a:6378160,rf:298.25,ellipseName:"Australian Natl & S. Amer. 1969"},GRS67:{a:6378160,rf:298.247167427,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,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,rf:298.3,ellipseName:"Fischer (Mercury Datum) 1960"},fschr60m:{a:6378155,rf:298.3,ellipseName:"Fischer 1960"},fschr68:{a:6378150,rf:298.3,ellipseName:"Fischer 1968"},helmert:{a:6378200,rf:298.3,ellipseName:"Helmert 1906"},hough:{a:6378270,rf:297,ellipseName:"Hough"},intl:{a:6378388,rf:297,ellipseName:"International 1909 (Hayford)"},kaula:{a:6378163,rf:298.24,ellipseName:"Kaula 1961"},lerch:{a:6378139,rf:298.257,ellipseName:"Lerch 1979"},mprts:{a:6397300,rf:191,ellipseName:"Maupertius 1738"}, +new_intl:{a:6378157.5,b:6356772.2,ellipseName:"New International 1967"},plessis:{a:6376523,rf:6355863,ellipseName:"Plessis 1817 (France)"},krass:{a:6378245,rf:298.3,ellipseName:"Krassovsky, 1942"},SEasia:{a:6378155,b:6356773.3205,ellipseName:"Southeast Asia"},walbeck:{a:6376896,b:6355834.8467,ellipseName:"Walbeck"},WGS60:{a:6378165,rf:298.3,ellipseName:"WGS 60"},WGS66:{a:6378145,rf:298.25,ellipseName:"WGS 66"},WGS72:{a:6378135,rf:298.26,ellipseName:"WGS 72"},WGS84:{a:6378137,rf:298.257223563,ellipseName:"WGS 84"}, +sphere:{a:6370997,b:6370997,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;Proj4js.wktProjections={"Lambert Tangential Conformal Conic Projection":"lcc",Mercator:"merc","Popular Visualisation Pseudo Mercator":"merc",Mercator_1SP:"merc",Transverse_Mercator:"tmerc","Transverse Mercator":"tmerc","Lambert Azimuthal Equal Area":"laea","Universal Transverse Mercator System":"utm"}; +Proj4js.Proj.aea={init:function(){Math.abs(this.lat1+this.lat2)Proj4js.common.EPSLN?(this.ms1*this.ms1-this.ms2*this.ms2)/(this.qs2-this.qs1):this.con,this.c=this.ms1*this.ms1+this.ns0*this.qs1,this.rh=this.a*Math.sqrt(this.c-this.ns0*this.qs0)/ +this.ns0)},forward:function(a){var c=a.x,b=a.y;this.sin_phi=Math.sin(b);this.cos_phi=Math.cos(b);var b=Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi),b=this.a*Math.sqrt(this.c-this.ns0*b)/this.ns0,d=this.ns0*Proj4js.common.adjust_lon(c-this.long0),c=b*Math.sin(d)+this.x0,b=this.rh-b*Math.cos(d)+this.y0;a.x=c;a.y=b;return a},inverse:function(a){var c,b,d;a.x-=this.x0;a.y=this.rh-a.y+this.y0;0<=this.ns0?(c=Math.sqrt(a.x*a.x+a.y*a.y),b=1):(c=-Math.sqrt(a.x*a.x+a.y*a.y),b=-1);d=0;0!=c&&(d=Math.atan2(b* +a.x,b*a.y));b=c*this.ns0/this.a;c=(this.c-b*b)/this.ns0;1.0E-10<=this.e3?(b=1-0.5*(1-this.es)*Math.log((1-this.e3)/(1+this.e3))/this.e3,b=1.0E-10=h;h++)if(b=Math.sin(g),d=Math.cos(g), +e=a*b,f=1-e*e,b=0.5*f*f/d*(c/(1-i)-b/f+0.5/a*Math.log((1-e)/(1+e))),g+=b,1.0E-7>=Math.abs(b))return g;Proj4js.reportError("aea:phi1z:Convergence error");return null}}; +Proj4js.Proj.sterea={dependsOn:"gauss",init:function(){Proj4js.Proj.gauss.init.apply(this);this.rc?(this.sinc0=Math.sin(this.phic0),this.cosc0=Math.cos(this.phic0),this.R2=2*this.rc,this.title||(this.title="Oblique Stereographic Alternative")):Proj4js.reportError("sterea:init:E_ERROR_0")},forward:function(a){var c,b,d,e;a.x=Proj4js.common.adjust_lon(a.x-this.long0);Proj4js.Proj.gauss.forward.apply(this,[a]);c=Math.sin(a.y);b=Math.cos(a.y);d=Math.cos(a.x);e=this.k0*this.R2/(1+this.sinc0*c+this.cosc0* +b*d);a.x=e*b*Math.sin(a.x);a.y=e*(this.cosc0*c-this.sinc0*b*d);a.x=this.a*a.x+this.x0;a.y=this.a*a.y+this.y0;return a},inverse:function(a){var c,b,d,e;a.x=(a.x-this.x0)/this.a;a.y=(a.y-this.y0)/this.a;a.x/=this.k0;a.y/=this.k0;(e=Math.sqrt(a.x*a.x+a.y*a.y))?(d=2*Math.atan2(e,this.R2),c=Math.sin(d),b=Math.cos(d),d=Math.asin(b*this.sinc0+a.y*c*this.cosc0/e),c=Math.atan2(a.x*c,e*this.cosc0*b-a.y*this.sinc0*c)):(d=this.phic0,c=0);a.x=c;a.y=d;Proj4js.Proj.gauss.inverse.apply(this,[a]);a.x=Proj4js.common.adjust_lon(a.x+ +this.long0);return a}};function phi4z(a,c,b,d,e,f,g,i,h){var j,k,l,m,n,o,h=f;for(o=1;15>=o;o++)if(j=Math.sin(h),l=Math.tan(h),i=l*Math.sqrt(1-a*j*j),k=Math.sin(2*h),m=c*h-b*k+d*Math.sin(4*h)-e*Math.sin(6*h),n=c-2*b*Math.cos(2*h)+4*d*Math.cos(4*h)-6*e*Math.cos(6*h),j=2*m+i*(m*m+g)-2*f*(i*m+1),l=a*k*(m*m+g-2*f*m)/(2*i),i=2*(f-m)*(i*n-2/k)-2*n,j/=l+i,h+=j,1.0E-10>=Math.abs(j))return h;Proj4js.reportError("phi4z: No convergence");return null} +function e4fn(a){var c;c=1+a;a=1-a;return Math.sqrt(Math.pow(c,c)*Math.pow(a,a))} +Proj4js.Proj.poly={init:function(){0==this.lat0&&(this.lat0=90);this.temp=this.b/this.a;this.es=1-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);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=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0)},forward:function(a){var c,b,d,e,f;d=a.y;b=Proj4js.common.adjust_lon(a.x-this.long0);1.0E-7>=Math.abs(d)?(f=this.x0+this.a*b,c=this.y0- +this.a*this.ml0):(c=Math.sin(d),b=Math.cos(d),d=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,d),e=Proj4js.common.msfnz(this.e,c,b),b=c,f=this.x0+this.a*e*Math.sin(b)/c,c=this.y0+this.a*(d-this.ml0+e*(1-Math.cos(b))/c));a.x=f;a.y=c;return a},inverse:function(a){var c,b;a.x-=this.x0;a.y-=this.y0;c=this.ml0+a.y/this.a;if(1.0E-7>=Math.abs(c))c=a.x/this.a+this.long0,b=0;else{c=c*c+a.x/this.a*(a.x/this.a);c=phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,c,void 0,b);if(1!=c)return c;c=Proj4js.common.adjust_lon(Proj4js.common.asinz(NaN* +a.x/this.a)/Math.sin(b)+this.long0)}a.x=c;a.y=b;return a}}; +Proj4js.Proj.equi={init:function(){this.x0||(this.x0=0);this.y0||(this.y0=0);this.lat0||(this.lat0=0);this.long0||(this.long0=0)},forward:function(a){var c=a.y,b=this.x0+this.a*Proj4js.common.adjust_lon(a.x-this.long0)*Math.cos(this.lat0),c=this.y0+this.a*c;this.t1=b;this.t2=Math.cos(this.lat0);a.x=b;a.y=c;return a},inverse:function(a){a.x-=this.x0;a.y-=this.y0;var c=a.y/this.a;Math.abs(c)>Proj4js.common.HALF_PI&&Proj4js.reportError("equi:Inv:DataError");var b=Proj4js.common.adjust_lon(this.long0+ +a.x/(this.a*Math.cos(this.lat0)));a.x=b;a.y=c}}; +Proj4js.Proj.merc={init:function(){this.lat_ts&&(this.k0=this.sphere?Math.cos(this.lat_ts):Proj4js.common.msfnz(this.es,Math.sin(this.lat_ts),Math.cos(this.lat_ts)))},forward:function(a){var c=a.x,b=a.y;if(90b*Proj4js.common.R2D&&180c*Proj4js.common.R2D)return Proj4js.reportError("merc:forward: llInputOutOfRange: "+c+" : "+b),null;if(Math.abs(Math.abs(b)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN)return Proj4js.reportError("merc:forward: ll2mAtPoles"),null; +if(this.sphere)c=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(c-this.long0),b=this.y0+this.a*this.k0*Math.log(Math.tan(Proj4js.common.FORTPI+0.5*b));else var d=Math.sin(b),b=Proj4js.common.tsfnz(this.e,b,d),c=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(c-this.long0),b=this.y0-this.a*this.k0*Math.log(b);a.x=c;a.y=b;return a},inverse:function(a){var c=a.x-this.x0,b=a.y-this.y0;if(this.sphere)b=Proj4js.common.HALF_PI-2*Math.atan(Math.exp(-b/this.a*this.k0));else if(b=Math.exp(-b/(this.a*this.k0)), +b=Proj4js.common.phi2z(this.e,b),-9999==b)return Proj4js.reportError("merc:inverse: lat = -9999"),null;c=Proj4js.common.adjust_lon(this.long0+c/(this.a*this.k0));a.x=c;a.y=b;return a}};Proj4js.Proj.utm={dependsOn:"tmerc",init:function(){this.zone?(this.lat0=0,this.long0=(6*Math.abs(this.zone)-183)*Proj4js.common.D2R,this.x0=5E5,this.y0=this.utmSouth?1E7:0,this.k0=0.9996,Proj4js.Proj.tmerc.init.apply(this),this.forward=Proj4js.Proj.tmerc.forward,this.inverse=Proj4js.Proj.tmerc.inverse):Proj4js.reportError("utm:init: zone must be specified for UTM")}}; +Proj4js.Proj.eqdc={init:function(){this.mode||(this.mode=0);this.temp=this.b/this.a;this.es=1-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);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.sinphi=Math.sin(this.lat1);this.cosphi=Math.cos(this.lat1);this.ms1=Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);this.ml1=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat1);0!=this.mode? +(Math.abs(this.lat1+this.lat2)=Proj4js.common.EPSLN?(this.ms1-this.ms2)/(this.ml2-this.ml1):this.sinphi):this.ns=this.sinphi;this.g=this.ml1+this.ms1/this.ns;this.ml0=Proj4js.common.mlfn(this.e0, +this.e1,this.e2,this.e3,this.lat0);this.rh=this.a*(this.g-this.ml0)},forward:function(a){var c=a.x,b=this.a*(this.g-Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,a.y)),d=this.ns*Proj4js.common.adjust_lon(c-this.long0),c=this.x0+b*Math.sin(d),b=this.y0+this.rh-b*Math.cos(d);a.x=c;a.y=b;return a},inverse:function(a){a.x-=this.x0;a.y=this.rh-a.y+this.y0;var c,b;0<=this.ns?(b=Math.sqrt(a.x*a.x+a.y*a.y),c=1):(b=-Math.sqrt(a.x*a.x+a.y*a.y),c=-1);var d=0;0!=b&&(d=Math.atan2(c*a.x,c*a.y));c=this.phi3z(this.g- +b/this.a,this.e0,this.e1,this.e2,this.e3);d=Proj4js.common.adjust_lon(this.long0+d/this.ns);a.x=d;a.y=c;return a},phi3z:function(a,c,b,d,e){var f,g;f=a;for(var i=0;15>i;i++)if(g=(a+b*Math.sin(2*f)-d*Math.sin(4*f)+e*Math.sin(6*f))/c-f,f+=g,1.0E-10>=Math.abs(g))return f;Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");return null}}; +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)},forward:function(a){var c=a.y,b=Proj4js.common.adjust_lon(a.x-this.long0),d,e;d=Math.sin(c);var f=Math.cos(c);if(this.sphere){var g=f*Math.sin(b);if(1.0E-10>Math.abs(Math.abs(g)-1))return Proj4js.reportError("tmerc:forward: Point projects into infinity"), +93;e=0.5*this.a*this.k0*Math.log((1+g)/(1-g));d=Math.acos(f*Math.cos(b)/Math.sqrt(1-g*g));0>c&&(d=-d);c=this.a*this.k0*(d-this.lat0)}else{e=f*b;var b=Math.pow(e,2),f=this.ep2*Math.pow(f,2),g=Math.tan(c),i=Math.pow(g,2);d=1-this.es*Math.pow(d,2);d=this.a/Math.sqrt(d);c=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,c);e=this.k0*d*e*(1+b/6*(1-i+f+b/20*(5-18*i+Math.pow(i,2)+72*f-58*this.ep2)))+this.x0;c=this.k0*(c-this.ml0+d*g*b*(0.5+b/24*(5-i+9*f+4*Math.pow(f,2)+b/30*(61-58*i+Math.pow(i, +2)+600*f-330*this.ep2))))+this.y0}a.x=e;a.y=c;return a},inverse:function(a){var c,b,d,e;if(this.sphere){b=Math.exp(a.x/(this.a*this.k0));var f=0.5*(b-1/b);d=this.lat0+a.y/(this.a*this.k0);e=Math.cos(d);c=Math.sqrt((1-e*e)/(1+f*f));b=Proj4js.common.asinz(c);0>d&&(b=-b);c=0==f&&0==e?this.long0:Proj4js.common.adjust_lon(Math.atan2(f,e)+this.long0)}else{var f=a.x-this.x0,g=a.y-this.y0;b=c=(this.ml0+g/this.k0)/this.a;for(e=0;;e++){d=(c+this.e1*Math.sin(2*b)-this.e2*Math.sin(4*b)+this.e3*Math.sin(6*b))/ +this.e0-b;b+=d;if(Math.abs(d)<=Proj4js.common.EPSLN)break;if(6<=e)return Proj4js.reportError("tmerc:inverse: Latitude failed to converge"),95}if(Math.abs(b)this.a+1.0E-7&&Proj4js.reportError("orthoInvDataError");b=Proj4js.common.asinz(c/this.a);d=Math.sin(b);e=Math.cos(b);b=this.long0;Math.abs(c);d=Proj4js.common.asinz(e*this.sin_p14+a.y*d*this.cos_p14/c);c=Math.abs(this.lat0)-Proj4js.common.HALF_PI;Math.abs(c)<=Proj4js.common.EPSLN&&(b=0<=this.lat0?Proj4js.common.adjust_lon(this.long0+Math.atan2(a.x,-a.y)):Proj4js.common.adjust_lon(this.long0-Math.atan2(-a.x,a.y)));Math.sin(d);a.x=b;a.y=d;return a}}; +Proj4js.Proj.krovak={init:function(){this.a=6377397.155;this.es=0.006674372230614;this.e=Math.sqrt(this.es);this.lat0||(this.lat0=0.863937979737193);this.long0||(this.long0=0.4334234309119251);this.k0||(this.k0=0.9999);this.s45=0.785398163397448;this.s90=2*this.s45;this.fi0=this.lat0;this.e2=this.es;this.e=Math.sqrt(this.e2);this.alfa=Math.sqrt(1+this.e2*Math.pow(Math.cos(this.fi0),4)/(1-this.e2));this.uq=1.04216856380474;this.u0=Math.asin(Math.sin(this.fi0)/this.alfa);this.g=Math.pow((1+this.e*Math.sin(this.fi0))/ +(1-this.e*Math.sin(this.fi0)),this.alfa*this.e/2);this.k=Math.tan(this.u0/2+this.s45)/Math.pow(Math.tan(this.fi0/2+this.s45),this.alfa)*this.g;this.k1=this.k0;this.n0=this.a*Math.sqrt(1-this.e2)/(1-this.e2*Math.pow(Math.sin(this.fi0),2));this.s0=1.37008346281555;this.n=Math.sin(this.s0);this.ro0=this.k1*this.n0/Math.tan(this.s0);this.ad=this.s90-this.uq},forward:function(a){var c,b,d;b=a.y;d=Proj4js.common.adjust_lon(a.x-this.long0);c=Math.pow((1+this.e*Math.sin(b))/(1-this.e*Math.sin(b)),this.alfa* +this.e/2);c=2*(Math.atan(this.k*Math.pow(Math.tan(b/2+this.s45),this.alfa)/c)-this.s45);b=-d*this.alfa;d=Math.asin(Math.cos(this.ad)*Math.sin(c)+Math.sin(this.ad)*Math.cos(c)*Math.cos(b));c=this.n*Math.asin(Math.cos(c)*Math.sin(b)/Math.cos(d));d=this.ro0*Math.pow(Math.tan(this.s0/2+this.s45),this.n)/Math.pow(Math.tan(d/2+this.s45),this.n);a.y=d*Math.cos(c)/1;a.x=d*Math.sin(c)/1;this.czech&&(a.y*=-1,a.x*=-1);return a},inverse:function(a){var c,b,d;c=a.x;a.x=a.y;a.y=c;this.czech&&(a.y*=-1,a.x*=-1); +c=Math.sqrt(a.x*a.x+a.y*a.y);b=Math.atan2(a.y,a.x)/Math.sin(this.s0);d=2*(Math.atan(Math.pow(this.ro0/c,1/this.n)*Math.tan(this.s0/2+this.s45))-this.s45);c=Math.asin(Math.cos(this.ad)*Math.sin(d)-Math.sin(this.ad)*Math.cos(d)*Math.cos(b));b=Math.asin(Math.cos(d)*Math.sin(b)/Math.cos(c));a.x=this.long0-b/this.alfa;b=c;var e=d=0;do a.y=2*(Math.atan(Math.pow(this.k,-1/this.alfa)*Math.pow(Math.tan(c/2+this.s45),1/this.alfa)*Math.pow((1+this.e*Math.sin(b))/(1-this.e*Math.sin(b)),this.e/2))-this.s45),1.0E-10> +Math.abs(b-a.y)&&(d=1),b=a.y,e+=1;while(0==d&&15>e);return 15<=e?(Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations"),null):a}}; +Proj4js.Proj.somerc={init:function(){var a=this.lat0;this.lambda0=this.long0;var c=Math.sin(a),b=this.a,d=1/this.rf,d=2*d-Math.pow(d,2),e=this.e=Math.sqrt(d);this.R=this.k0*b*Math.sqrt(1-d)/(1-d*Math.pow(c,2));this.alpha=Math.sqrt(1+d/(1-d)*Math.pow(Math.cos(a),4));this.b0=Math.asin(c/this.alpha);this.K=Math.log(Math.tan(Math.PI/4+this.b0/2))-this.alpha*Math.log(Math.tan(Math.PI/4+a/2))+this.alpha*e/2*Math.log((1+e*c)/(1-e*c))},forward:function(a){var c=Math.log(Math.tan(Math.PI/4-a.y/2)),b=this.e/ +2*Math.log((1+this.e*Math.sin(a.y))/(1-this.e*Math.sin(a.y))),b=2*(Math.atan(Math.exp(-this.alpha*(c+b)+this.K))-Math.PI/4),d=this.alpha*(a.x-this.lambda0),c=Math.atan(Math.sin(d)/(Math.sin(this.b0)*Math.tan(b)+Math.cos(this.b0)*Math.cos(d))),b=Math.asin(Math.cos(this.b0)*Math.sin(b)-Math.sin(this.b0)*Math.cos(b)*Math.cos(d));a.y=this.R/2*Math.log((1+Math.sin(b))/(1-Math.sin(b)))+this.y0;a.x=this.R*c+this.x0;return a},inverse:function(a){for(var c=(a.x-this.x0)/this.R,b=2*(Math.atan(Math.exp((a.y- +this.y0)/this.R))-Math.PI/4),d=Math.asin(Math.cos(this.b0)*Math.sin(b)+Math.sin(this.b0)*Math.cos(b)*Math.cos(c)),c=this.lambda0+Math.atan(Math.sin(c)/(Math.cos(this.b0)*Math.cos(c)-Math.sin(this.b0)*Math.tan(b)))/this.alpha,b=0,e=d,f=-1E3,g=0;1.0E-7this.lat0?this.S_POLE:this.N_POLE:a>Proj4js.common.EPSLN?this.OBLIQ:this.EQUIT;this.phits=Math.abs(this.phits);if(this.es){var c;switch(this.mode){case this.N_POLE:case this.S_POLE:Math.abs(this.phits-Proj4js.common.HALF_PI)< +Proj4js.common.EPSLN?this.akm1=2*this.k0/Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e)):(a=Math.sin(this.phits),this.akm1=Math.cos(this.phits)/Proj4js.common.tsfnz(this.e,this.phits,a),a*=this.e,this.akm1/=Math.sqrt(1-a*a));break;case this.EQUIT:this.akm1=2*this.k0;break;case this.OBLIQ:a=Math.sin(this.lat0),c=2*Math.atan(this.ssfn_(this.lat0,a,this.e))-Proj4js.common.HALF_PI,a*=this.e,this.akm1=2*this.k0*Math.cos(this.lat0)/Math.sqrt(1-a*a),this.sinX1=Math.sin(c),this.cosX1=Math.cos(c)}}else switch(this.mode){case this.OBLIQ:this.sinph0= +Math.sin(this.lat0),this.cosph0=Math.cos(this.lat0);case this.EQUIT:this.akm1=2*this.k0;break;case this.S_POLE:case this.N_POLE:this.akm1=Math.abs(this.phits-Proj4js.common.HALF_PI)>=Proj4js.common.EPSLN?Math.cos(this.phits)/Math.tan(Proj4js.common.FORTPI-0.5*this.phits):2*this.k0}},forward:function(a){var c=a.x,c=Proj4js.common.adjust_lon(c-this.long0),b=a.y,d,e;if(this.sphere){var f,g,i;f=Math.sin(b);g=Math.cos(b);i=Math.cos(c);c=Math.sin(c);switch(this.mode){case this.EQUIT:e=1+g*i;e<=Proj4js.common.EPSLN&& +Proj4js.reportError("stere:forward:Equit");e=this.akm1/e;d=e*g*c;e*=f;break;case this.OBLIQ:e=1+this.sinph0*f+this.cosph0*g*i;e<=Proj4js.common.EPSLN&&Proj4js.reportError("stere:forward:Obliq");e=this.akm1/e;d=e*g*c;e*=this.cosph0*f-this.sinph0*g*i;break;case this.N_POLE:i=-i,b=-b;case this.S_POLE:Math.abs(b-Proj4js.common.HALF_PI)=f;f++)d*=c,e+=this.A[f]*d;for(var c=e,d=1,g=0,i=0,h=0,f=1;6>=f;f++)e=d*c-g*b,g=g*c+d*b,d=e,i=i+this.B_re[f]*d-this.B_im[f]*g,h=h+this.B_im[f]*d+this.B_re[f]*g;a.x=h*this.a+this.x0;a.y=i*this.a+this.y0;return a},inverse:function(a){for(var c=(a.y-this.y0)/this.a,b=(a.x-this.x0)/this.a,d=1,e=0,f,g=0,i=0,h=1;6>=h;h++)f= +d*c-e*b,e=e*c+d*b,d=f,g=g+this.C_re[h]*d-this.C_im[h]*e,i=i+this.C_im[h]*d+this.C_re[h]*e;for(d=0;d=h;h++)l=j*g-k*i,k=k*g+j*i,j=l,f+=(h-1)*(this.B_re[h]*j-this.B_im[h]*k),e+=(h-1)*(this.B_im[h]*j+this.B_re[h]*k);for(var j=1,k=0,m=this.B_re[1],n=this.B_im[1],h=2;6>=h;h++)l=j*g-k*i,k=k*g+j*i,j=l,m+=h*(this.B_re[h]*j-this.B_im[h]*k),n+=h*(this.B_im[h]*j+this.B_re[h]*k);i=m*m+n*n;g=(f*m+e*n)/i;i=(e*m-f*n)/i}c=g;b=1;g=0;for(h=1;9>=h;h++)b*=c,g+=this.D[h]* +b;h=this.lat0+1E5*g*Proj4js.common.SEC_TO_RAD;a.x=this.long0+i;a.y=h;return a}};Proj4js.Proj.mill={init:function(){},forward:function(a){var c=a.y,b=this.x0+this.a*Proj4js.common.adjust_lon(a.x-this.long0),c=this.y0+1.25*this.a*Math.log(Math.tan(Proj4js.common.PI/4+c/2.5));a.x=b;a.y=c;return a},inverse:function(a){a.x-=this.x0;a.y-=this.y0;var c=Proj4js.common.adjust_lon(this.long0+a.x/this.a),b=2.5*(Math.atan(Math.exp(0.8*a.y/this.a))-Proj4js.common.PI/4);a.x=c;a.y=b;return a}}; +Proj4js.Proj.gnom={init:function(){this.sin_p14=Math.sin(this.lat0);this.cos_p14=Math.cos(this.lat0);this.infinity_dist=1E3*this.a;this.rc=1},forward:function(a){var c,b,d,e,f;b=a.y;d=Proj4js.common.adjust_lon(a.x-this.long0);c=Math.sin(b);b=Math.cos(b);e=Math.cos(d);f=this.sin_p14*c+this.cos_p14*b*e;0b&&(f=-f);b=this.x0+f;f=Math.abs(f/(Proj4js.common.PI*this.R));c=0<=c?this.y0+Proj4js.common.PI*this.R*Math.sqrt(1-f*f-2*e*f):this.y0-Proj4js.common.PI*this.R*Math.sqrt(1-f*f-2*e*f);a.x=b;a.y=c;return a},inverse:function(a){var c,b,d,e,f,g,i,h;a.x-=this.x0;a.y-=this.y0;h=Proj4js.common.PI*this.R;c=a.x/h;d=a.y/h;e=c*c+d*d;f=-Math.abs(d)*(1+e);b=f-2*d*d+c*c;g=-2*f+1+2*d*d+e*e;h=d*d/g+(2*b*b*b/g/g/g-9*f*b/g/g)/27;i=(f-b*b/3/g)/g;f=2*Math.sqrt(-i/3);h=3*h/i/f;1Math.abs(b-a.y))break;a.y=b}if(!e)return Proj4js.reportError("gauss:inverse:convergence failed"),null;a.x=c;a.y=b;return a}}; +Proj4js.Proj.omerc={init:function(){this.mode||(this.mode=0);this.lon1||(this.lon1=0,this.mode=1);this.lon2||(this.lon2=0);this.lat2||(this.lat2=0);var a=1-Math.pow(this.b/this.a,2);Math.sqrt(a);this.sin_p20=Math.sin(this.lat0);this.cos_p20=Math.cos(this.lat0);this.con=1-this.es*this.sin_p20*this.sin_p20;this.com=Math.sqrt(1-a);this.bl=Math.sqrt(1+this.es*Math.pow(this.cos_p20,4)/(1-a));this.al=this.a*this.bl*this.k0*this.com/this.con;Math.abs(this.lat0) +Proj4js.common.EPSLN&&Math.abs(this.con-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN?(this.singam=Math.sin(this.gama),this.cosgam=Math.cos(this.gama),this.sinaz=Math.sin(this.alpha),this.cosaz=Math.cos(this.alpha),this.u=0<=this.lat0?this.al/this.bl*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz):-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz)):Proj4js.reportError("omerc:Init:DataError")):(this.sinphi=Math.sin(this.at1),this.ts1=Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi), +this.sinphi=Math.sin(this.lat2),this.ts2=Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi),this.h=Math.pow(this.ts1,this.bl),this.l=Math.pow(this.ts2,this.bl),this.f=this.el/this.h,this.g=0.5*(this.f-1/this.f),this.j=(this.el*this.el-this.l*this.h)/(this.el*this.el+this.l*this.h),this.p=(this.l-this.h)/(this.l+this.h),this.dlon=this.lon1-this.lon2,this.dlon<-Proj4js.common.PI&&(this.lon2-=2*Proj4js.common.PI),this.dlon>Proj4js.common.PI&&(this.lon2+=2*Proj4js.common.PI),this.dlon=this.lon1-this.lon2, +this.longc=0.5*(this.lon1+this.lon2)-Math.atan(this.j*Math.tan(0.5*this.bl*this.dlon)/this.p)/this.bl,this.dlon=Proj4js.common.adjust_lon(this.lon1-this.longc),this.gama=Math.atan(Math.sin(this.bl*this.dlon)/this.g),this.alpha=Proj4js.common.asinz(this.d*Math.sin(this.gama)),Math.abs(this.lat1-this.lat2)<=Proj4js.common.EPSLN?Proj4js.reportError("omercInitDataError"):this.con=Math.abs(this.lat1),this.con<=Proj4js.common.EPSLN||Math.abs(this.con-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN?Proj4js.reportError("omercInitDataError"): +Math.abs(Math.abs(this.lat0)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN&&Proj4js.reportError("omercInitDataError"),this.singam=Math.sin(this.gam),this.cosgam=Math.cos(this.gam),this.sinaz=Math.sin(this.alpha),this.cosaz=Math.cos(this.alpha),this.u=0<=this.lat0?this.al/this.bl*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz):-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz))},forward:function(a){var c,b,d,e,f;d=a.x;b=a.y;c=Math.sin(b);e=Proj4js.common.adjust_lon(d-this.longc); +d=Math.sin(this.bl*e);Math.abs(Math.abs(b)-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN?(c=Proj4js.common.tsfnz(this.e,b,c),c=this.el/Math.pow(c,this.bl),f=0.5*(c-1/c),c=(f*this.singam-d*this.cosgam)/(0.5*(c+1/c)),b=Math.cos(this.bl*e),1.0E-7>Math.abs(b)?d=this.al*this.bl*e:(d=this.al*Math.atan((f*this.cosgam+d*this.singam)/b)/this.bl,0>b&&(d+=Proj4js.common.PI*this.al/this.bl))):(c=0<=b?this.singam:-this.singam,d=this.al*b/this.bl);Math.abs(Math.abs(c)-1)<=Proj4js.common.EPSLN&&Proj4js.reportError("omercFwdInfinity"); +e=0.5*this.al*Math.log((1-c)/(1+c))/this.bl;d-=this.u;c=this.y0+d*this.cosaz-e*this.sinaz;a.x=this.x0+e*this.cosaz+d*this.sinaz;a.y=c;return a},inverse:function(a){var c,b,d,e;a.x-=this.x0;a.y-=this.y0;c=a.x*this.cosaz-a.y*this.sinaz;d=a.y*this.cosaz+a.x*this.sinaz;d+=this.u;b=Math.exp(-this.bl*c/this.al);c=0.5*(b-1/b);b=0.5*(b+1/b);d=Math.sin(this.bl*d/this.al);e=(d*this.cosgam+c*this.singam)/b;Math.abs(Math.abs(e)-1)<=Proj4js.common.EPSLN?(c=this.longc,e=0<=e?Proj4js.common.HALF_PI:-Proj4js.common.HALF_PI): +(b=1/this.bl,e=Math.pow(this.el/Math.sqrt((1+e)/(1-e)),b),e=Proj4js.common.phi2z(this.e,e),c=this.longc-Math.atan2(c*this.cosgam-d*this.singam,b)/this.bl,c=Proj4js.common.adjust_lon(c));a.x=c;a.y=e;return a}}; +Proj4js.Proj.lcc={init:function(){this.lat2||(this.lat2=this.lat0);this.k0||(this.k0=1);if(Math.abs(this.lat1+this.lat2)Proj4js.common.EPSLN?Math.log(c/e)/Math.log(b/d):a;this.f0=c/(this.ns*Math.pow(b,this.ns));this.rh=this.a*this.f0*Math.pow(f,this.ns);this.title||(this.title="Lambert Conformal Conic")}},forward:function(a){var c=a.x,b=a.y;if(!(90>=b&&-90<=b&&180>=c&&-180<=c))return Proj4js.reportError("lcc:forward: llInputOutOfRange: "+c+" : "+b),null;var d=Math.abs(Math.abs(b)-Proj4js.common.HALF_PI);if(d>Proj4js.common.EPSLN)b=Proj4js.common.tsfnz(this.e, +b,Math.sin(b)),b=this.a*this.f0*Math.pow(b,this.ns);else{d=b*this.ns;if(0>=d)return Proj4js.reportError("lcc:forward: No Projection"),null;b=0}c=this.ns*Proj4js.common.adjust_lon(c-this.long0);a.x=this.k0*b*Math.sin(c)+this.x0;a.y=this.k0*(this.rh-b*Math.cos(c))+this.y0;return a},inverse:function(a){var c,b,d,e=(a.x-this.x0)/this.k0,f=this.rh-(a.y-this.y0)/this.k0;0this.lat0?this.S_POLE:this.N_POLE:Math.abs(a)g){Proj4js.reportError("aeqd:Fwd:PointError");return}}else b=Math.acos(g),b/=Math.sin(b);a.x=this.x0+this.a*b*e*Math.sin(c);a.y=this.y0+this.a*b*(this.cos_p12*d-this.sin_p12*e*f);return a}, +inverse:function(a){a.x-=this.x0;a.y-=this.y0;var c=Math.sqrt(a.x*a.x+a.y*a.y);if(c>2*Proj4js.common.HALF_PI*this.a)Proj4js.reportError("aeqdInvDataError");else{var b=c/this.a,d=Math.sin(b),b=Math.cos(b),e=this.long0,f;if(Math.abs(c)<=Proj4js.common.EPSLN)f=this.lat0;else{f=Proj4js.common.asinz(b*this.sin_p12+a.y*d*this.cos_p12/c);var g=Math.abs(this.lat0)-Proj4js.common.HALF_PI;Math.abs(g)<=Proj4js.common.EPSLN?e=0<=this.lat0?Proj4js.common.adjust_lon(this.long0+Math.atan2(a.x,-a.y)):Proj4js.common.adjust_lon(this.long0- +Math.atan2(-a.x,a.y)):(g=b-this.sin_p12*Math.sin(f),Math.abs(g)Proj4js.common.PI&&(b=Proj4js.common.PI);c=(2*c+Math.sin(2*c))/Proj4js.common.PI;1 tag or Proj4js can load CS initialization + * strings from a local directory or a web service such as spatialreference.org. + * + * Similarly, Proj4js must have access to projection transform code. These can + * be included individually 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", + 'EPSG:3875': "+title= Google Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs" +}; +Proj4js.defs['EPSG:3785'] = Proj4js.defs['EPSG:3875']; //maintain backward compat, official code is 3875 +Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3875']; +Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3875']; +Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3875']; + +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 (var 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) { + 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 Schreiber +// 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); + }, + + //code from the PROJ.4 pj_mlfn.c file; this may be useful for other projections + pj_enfn: function(es) { + var en = new Array(); + en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08))); + en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08))); + var t = es * es; + en[2] = t * (this.C44 - es * (this.C46 + es * this.C48)); + t *= es; + en[3] = t * (this.C66 - es * this.C68); + en[4] = t * es * this.C88; + return en; + }, + + pj_mlfn: function(phi, sphi, cphi, en) { + cphi *= sphi; + sphi *= sphi; + return(en[0] * phi - cphi * (en[1] + sphi*(en[2]+ sphi*(en[3] + sphi*en[4])))); + }, + + pj_inv_mlfn: function(arg, es, en) { + var k = 1./(1.-es); + var phi = arg; + for (var i = Proj4js.common.MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */ + var s = Math.sin(phi); + var t = 1. - es * s * s; + //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg; + //phi -= t * (t * Math.sqrt(t)) * k; + t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k; + phi -= t; + if (Math.abs(t) < Proj4js.common.EPSLN) + return phi; + } + Proj4js.reportError("cass:pj_inv_mlfn: Convergence error"); + return phi; + }, + +/* meridinal distance for ellipsoid and inverse +** 8th degree - accurate to < 1e-5 meters when used in conjuction +** with typical major axis values. +** Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds. +*/ + C00: 1.0, + C02: .25, + C04: .046875, + C06: .01953125, + C08: .01068115234375, + C22: .75, + C44: .46875, + C46: .01302083333333333333, + C48: .00712076822916666666, + C66: .36458333333333333333, + C68: .00569661458333333333, + C88: .3076171875 + +}; + +/** 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 TRUE if the two datums match, otherwise 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 || + dest.datum_type == Proj4js.common.PJD_GRIDSHIFT ) { + alert("ERROR: Grid shift transformations are not implemented."); + return false + } 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' && typeof y == 'undefined') { + 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 + +//lookup table to go from the projection name in WKT to the Proj4js projection name +//build this out as required +Proj4js.wktProjections = { + "Lambert Tangential Conformal Conic Projection": "lcc", + "Mercator": "merc", + "Popular Visualisation Pseudo Mercator": "merc", + "Mercator_1SP": "merc", + "Transverse_Mercator": "tmerc", + "Transverse Mercator": "tmerc", + "Lambert Azimuthal Equal Area": "laea", + "Universal Transverse Mercator System": "utm" +}; + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/aea.js b/src/main/webapp/com/plugins/proj4js/projCode/aea.js new file mode 100644 index 0000000..cb4fc2f --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/aea.js @@ -0,0 +1,149 @@ +/******************************************************************************* +NAME ALBERS CONICAL EQUAL AREA + +PURPOSE: Transforms input longitude and latitude to Easting and Northing + for the Albers Conical Equal Area projection. The longitude + and latitude must be in radians. The Easting and Northing + values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan, Feb, 1992 + +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. +*******************************************************************************/ + + +Proj4js.Proj.aea = { + init : function() { + + if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) { + Proj4js.reportError("aeaInitEqualLatitudes"); + return; + } + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2); + this.e3 = Math.sqrt(this.es); + + this.sin_po=Math.sin(this.lat1); + this.cos_po=Math.cos(this.lat1); + this.t1=this.sin_po; + this.con = this.sin_po; + this.ms1 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po); + this.qs1 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po); + + this.sin_po=Math.sin(this.lat2); + this.cos_po=Math.cos(this.lat2); + this.t2=this.sin_po; + this.ms2 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po); + this.qs2 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po); + + this.sin_po=Math.sin(this.lat0); + this.cos_po=Math.cos(this.lat0); + this.t3=this.sin_po; + this.qs0 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po); + + if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) { + this.ns0 = (this.ms1 * this.ms1 - this.ms2 *this.ms2)/ (this.qs2 - this.qs1); + } else { + this.ns0 = this.con; + } + this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1; + this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0)/this.ns0; + }, + +/* Albers Conical Equal Area forward equations--mapping lat,long to x,y + -------------------------------------------------------------------*/ + forward: function(p){ + + var lon=p.x; + var lat=p.y; + + this.sin_phi=Math.sin(lat); + this.cos_phi=Math.cos(lat); + + var qs = Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi); + var rh1 =this.a * Math.sqrt(this.c - this.ns0 * qs)/this.ns0; + var theta = this.ns0 * Proj4js.common.adjust_lon(lon - this.long0); + var x = rh1 * Math.sin(theta) + this.x0; + var y = this.rh - rh1 * Math.cos(theta) + this.y0; + + p.x = x; + p.y = y; + return p; + }, + + + inverse: function(p) { + var rh1,qs,con,theta,lon,lat; + + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + if (this.ns0 >= 0) { + rh1 = Math.sqrt(p.x *p.x + p.y * p.y); + con = 1.0; + } else { + rh1 = -Math.sqrt(p.x * p.x + p.y *p.y); + con = -1.0; + } + theta = 0.0; + if (rh1 != 0.0) { + theta = Math.atan2(con * p.x, con * p.y); + } + con = rh1 * this.ns0 / this.a; + qs = (this.c - con * con) / this.ns0; + if (this.e3 >= 1e-10) { + con = 1 - .5 * (1.0 -this.es) * Math.log((1.0 - this.e3) / (1.0 + this.e3))/this.e3; + if (Math.abs(Math.abs(con) - Math.abs(qs)) > .0000000001 ) { + lat = this.phi1z(this.e3,qs); + } else { + if (qs >= 0) { + lat = .5 * Proj4js.common.PI; + } else { + lat = -.5 * Proj4js.common.PI; + } + } + } else { + lat = this.phi1z(this.e3,qs); + } + + lon = Proj4js.common.adjust_lon(theta/this.ns0 + this.long0); + p.x = lon; + p.y = lat; + return p; + }, + +/* Function to compute phi1, the latitude for the inverse of the + Albers Conical Equal-Area projection. +-------------------------------------------*/ + phi1z: function (eccent,qs) { + var sinphi, cosphi, con, com, dphi; + var phi = Proj4js.common.asinz(.5 * qs); + if (eccent < Proj4js.common.EPSLN) return phi; + + var eccnts = eccent * eccent; + for (var i = 1; i <= 25; i++) { + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + con = eccent * sinphi; + com = 1.0 - con * con; + dphi = .5 * com * com / cosphi * (qs / (1.0 - eccnts) - sinphi / com + .5 / eccent * Math.log((1.0 - con) / (1.0 + con))); + phi = phi + dphi; + if (Math.abs(dphi) <= 1e-7) return phi; + } + Proj4js.reportError("aea:phi1z:Convergence error"); + return null; + } + +}; + + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/aeqd.js b/src/main/webapp/com/plugins/proj4js/projCode/aeqd.js new file mode 100644 index 0000000..334ce3c --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/aeqd.js @@ -0,0 +1,75 @@ +Proj4js.Proj.aeqd = { + + init : function() { + this.sin_p12=Math.sin(this.lat0); + this.cos_p12=Math.cos(this.lat0); + }, + + forward: function(p) { + var lon=p.x; + var lat=p.y; + var ksp; + + var sinphi=Math.sin(p.y); + var cosphi=Math.cos(p.y); + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var coslon = Math.cos(dlon); + var g = this.sin_p12 * sinphi + this.cos_p12 * cosphi * coslon; + if (Math.abs(Math.abs(g) - 1.0) < Proj4js.common.EPSLN) { + ksp = 1.0; + if (g < 0.0) { + Proj4js.reportError("aeqd:Fwd:PointError"); + return; + } + } else { + var z = Math.acos(g); + ksp = z/Math.sin(z); + } + p.x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon); + p.y = this.y0 + this.a * ksp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * coslon); + return p; + }, + + inverse: function(p){ + p.x -= this.x0; + p.y -= this.y0; + + var rh = Math.sqrt(p.x * p.x + p.y *p.y); + if (rh > (2.0 * Proj4js.common.HALF_PI * this.a)) { + Proj4js.reportError("aeqdInvDataError"); + return; + } + var z = rh / this.a; + + var sinz=Math.sin(z); + var cosz=Math.cos(z); + + var lon = this.long0; + var lat; + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.lat0; + } else { + lat = Proj4js.common.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh); + var con = Math.abs(this.lat0) - Proj4js.common.HALF_PI; + if (Math.abs(con) <= Proj4js.common.EPSLN) { + if (this.lat0 >= 0.0) { + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x , -p.y)); + } else { + lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x , p.y)); + } + } else { + con = cosz - this.sin_p12 * Math.sin(lat); + if ((Math.abs(con) < Proj4js.common.EPSLN) && (Math.abs(p.x) < Proj4js.common.EPSLN)) { + //no-op, just keep the lon value as is + } else { + var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh)); + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh))); + } + } + } + + p.x = lon; + p.y = lat; + return p; + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/cass.js b/src/main/webapp/com/plugins/proj4js/projCode/cass.js new file mode 100644 index 0000000..ef62945 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/cass.js @@ -0,0 +1,108 @@ +/******************************************************************************* +NAME CASSINI + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Cassini projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + Ported from PROJ.4. + + +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 +*******************************************************************************/ + + +//Proj4js.defs["EPSG:28191"] = "+proj=cass +lat_0=31.73409694444445 +lon_0=35.21208055555556 +x_0=170251.555 +y_0=126867.909 +a=6378300.789 +b=6356566.435 +towgs84=-275.722,94.7824,340.894,-8.001,-4.42,-11.821,1 +units=m +no_defs"; + +// Initialize the Cassini projection +// ----------------------------------------------------------------- + +Proj4js.Proj.cass = { + init : function() { + if (!this.sphere) { + this.en = Proj4js.common.pj_enfn(this.es) + this.m0 = Proj4js.common.pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en); + } + }, + + C1: .16666666666666666666, + C2: .00833333333333333333, + C3: .04166666666666666666, + C4: .33333333333333333333, + C5: .06666666666666666666, + + +/* Cassini forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ + forward: function(p) { + + /* Forward equations + -----------------*/ + var x,y; + var lam=p.x; + var phi=p.y; + lam = Proj4js.common.adjust_lon(lam - this.long0); + + if (this.sphere) { + x = Math.asin(Math.cos(phi) * Math.sin(lam)); + y = Math.atan2(Math.tan(phi) , Math.cos(lam)) - this.phi0; + } else { + //ellipsoid + this.n = Math.sin(phi); + this.c = Math.cos(phi); + y = Proj4js.common.pj_mlfn(phi, this.n, this.c, this.en); + this.n = 1./Math.sqrt(1. - this.es * this.n * this.n); + this.tn = Math.tan(phi); + this.t = this.tn * this.tn; + this.a1 = lam * this.c; + this.c *= this.es * this.c / (1 - this.es); + this.a2 = this.a1 * this.a1; + x = this.n * this.a1 * (1. - this.a2 * this.t * (this.C1 - (8. - this.t + 8. * this.c) * this.a2 * this.C2)); + y -= this.m0 - this.n * this.tn * this.a2 * (.5 + (5. - this.t + 6. * this.c) * this.a2 * this.C3); + } + + p.x = this.a*x + this.x0; + p.y = this.a*y + this.y0; + return p; + },//cassFwd() + +/* Inverse equations + -----------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + var x = p.x/this.a; + var y = p.y/this.a; + var phi, lam; + + if (this.sphere) { + this.dd = y + this.lat0; + phi = Math.asin(Math.sin(this.dd) * Math.cos(x)); + lam = Math.atan2(Math.tan(x), Math.cos(this.dd)); + } else { + /* ellipsoid */ + var ph1 = Proj4js.common.pj_inv_mlfn(this.m0 + y, this.es, this.en); + this.tn = Math.tan(ph1); + this.t = this.tn * this.tn; + this.n = Math.sin(ph1); + this.r = 1. / (1. - this.es * this.n * this.n); + this.n = Math.sqrt(this.r); + this.r *= (1. - this.es) * this.n; + this.dd = x / this.n; + this.d2 = this.dd * this.dd; + phi = ph1 - (this.n * this.tn / this.r) * this.d2 * (.5 - (1. + 3. * this.t) * this.d2 * this.C3); + lam = this.dd * (1. + this.t * this.d2 * (-this.C4 + (1. + 3. * this.t) * this.d2 * this.C5)) / Math.cos(ph1); + } + p.x = Proj4js.common.adjust_lon(this.long0+lam); + p.y = phi; + return p; + }//cassInv() + +} diff --git a/src/main/webapp/com/plugins/proj4js/projCode/cea.js b/src/main/webapp/com/plugins/proj4js/projCode/cea.js new file mode 100644 index 0000000..9ed4ac9 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/cea.js @@ -0,0 +1,85 @@ +/******************************************************************************* +NAME LAMBERT CYLINDRICAL EQUAL AREA + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Cylindrical Equal Area projection. + This class of projection includes the Behrmann and + Gall-Peters Projections. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +R. Marsden August 2009 +Winwaed Software Tech LLC, http://www.winwaed.com + +This function was adapted from the Miller Cylindrical Projection in the Proj4JS +library. + +Note: This implementation assumes a Spherical Earth. The (commented) code +has been included for the ellipsoidal forward transform, but derivation of +the ellispoidal inverse transform is beyond me. Note that most of the +Proj4JS implementations do NOT currently support ellipsoidal figures. +Therefore this is not seen as a problem - especially this lack of support +is explicitly stated here. + +ALGORITHM REFERENCES + +1. "Cartographic Projection Procedures for the UNIX Environment - + A User's Manual" by Gerald I. Evenden, USGS Open File Report 90-284 + and Release 4 Interim Reports (2003) + +2. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map + Projections", Univ. Chicago Press, 1993 +*******************************************************************************/ + +Proj4js.Proj.cea = { + +/* Initialize the Cylindrical Equal Area projection + -------------------------------------------*/ + init: function() { + //no-op + }, + + + /* Cylindrical Equal Area forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ + forward: function(p) { + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + var dlon = Proj4js.common.adjust_lon(lon -this.long0); + var x = this.x0 + this.a * dlon * Math.cos(this.lat_ts); + var y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts); + /* Elliptical Forward Transform + Not implemented due to a lack of a matchign inverse function + { + var Sin_Lat = Math.sin(lat); + var Rn = this.a * (Math.sqrt(1.0e0 - this.es * Sin_Lat * Sin_Lat )); + x = this.x0 + this.a * dlon * Math.cos(this.lat_ts); + y = this.y0 + Rn * Math.sin(lat) / Math.cos(this.lat_ts); + } + */ + + + p.x=x; + p.y=y; + return p; + },//ceaFwd() + + /* Cylindrical Equal Area inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + + var lon = Proj4js.common.adjust_lon( this.long0 + (p.x / this.a) / Math.cos(this.lat_ts) ); + + var lat = Math.asin( (p.y/this.a) * Math.cos(this.lat_ts) ); + + p.x=lon; + p.y=lat; + return p; + }//ceaInv() +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/eqc.js b/src/main/webapp/com/plugins/proj4js/projCode/eqc.js new file mode 100644 index 0000000..284fdde --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/eqc.js @@ -0,0 +1,42 @@ +/* similar to equi.js FIXME proj4 uses eqc */ +Proj4js.Proj.eqc = { + init : function() { + + if(!this.x0) this.x0=0; + if(!this.y0) this.y0=0; + if(!this.lat0) this.lat0=0; + if(!this.long0) this.long0=0; + if(!this.lat_ts) this.lat_ts=0; + if (!this.title) this.title = "Equidistant Cylindrical (Plate Carre)"; + + this.rc= Math.cos(this.lat_ts); + }, + + + // forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + forward : function(p) { + + var lon= p.x; + var lat= p.y; + + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var dlat = Proj4js.common.adjust_lat(lat - this.lat0 ); + p.x= this.x0 + (this.a*dlon*this.rc); + p.y= this.y0 + (this.a*dlat ); + return p; + }, + + // inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + inverse : function(p) { + + var x= p.x; + var y= p.y; + + p.x= Proj4js.common.adjust_lon(this.long0 + ((x - this.x0)/(this.a*this.rc))); + p.y= Proj4js.common.adjust_lat(this.lat0 + ((y - this.y0)/(this.a ))); + return p; + } + +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/eqdc.js b/src/main/webapp/com/plugins/proj4js/projCode/eqdc.js new file mode 100644 index 0000000..7229df9 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/eqdc.js @@ -0,0 +1,140 @@ +/******************************************************************************* +NAME EQUIDISTANT CONIC + +PURPOSE: Transforms input longitude and latitude to Easting and Northing + for the Equidistant Conic projection. The longitude and + latitude must be in radians. The Easting and Northing values + will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +/* Variables common to all subroutines in this code file + -----------------------------------------------------*/ + +Proj4js.Proj.eqdc = { + +/* Initialize the Equidistant Conic projection + ------------------------------------------*/ + init: function() { + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + + if(!this.mode) this.mode=0;//chosen default mode + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2); + this.e = Math.sqrt(this.es); + 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.sinphi=Math.sin(this.lat1); + this.cosphi=Math.cos(this.lat1); + + this.ms1 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi); + this.ml1 = Proj4js.common.mlfn(this.e0, this.e1, this.e2,this.e3, this.lat1); + + /* format B + ---------*/ + if (this.mode != 0) { + if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) { + Proj4js.reportError("eqdc:Init:EqualLatitudes"); + //return(81); + } + this.sinphi=Math.sin(this.lat2); + this.cosphi=Math.cos(this.lat2); + + this.ms2 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi); + this.ml2 = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2); + if (Math.abs(this.lat1 - this.lat2) >= Proj4js.common.EPSLN) { + this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1); + } else { + this.ns = this.sinphi; + } + } else { + this.ns = this.sinphi; + } + this.g = this.ml1 + this.ms1/this.ns; + this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this. e2, this.e3, this.lat0); + this.rh = this.a * (this.g - this.ml0); + }, + + +/* Equidistant Conic forward equations--mapping lat,long to x,y + -----------------------------------------------------------*/ + forward: function(p) { + var lon=p.x; + var lat=p.y; + + /* Forward equations + -----------------*/ + var ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + var rh1 = this.a * (this.g - ml); + var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0); + + var x = this.x0 + rh1 * Math.sin(theta); + var y = this.y0 + this.rh - rh1 * Math.cos(theta); + p.x=x; + p.y=y; + return p; + }, + +/* Inverse equations + -----------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y = this.rh - p.y + this.y0; + var con, rh1; + if (this.ns >= 0) { + rh1 = Math.sqrt(p.x *p.x + p.y * p.y); + con = 1.0; + } else { + rh1 = -Math.sqrt(p.x *p. x +p. y * p.y); + con = -1.0; + } + var theta = 0.0; + if (rh1 != 0.0) theta = Math.atan2(con *p.x, con *p.y); + var ml = this.g - rh1 /this.a; + var lat = this.phi3z(ml,this.e0,this.e1,this.e2,this.e3); + var lon = Proj4js.common.adjust_lon(this.long0 + theta / this.ns); + + p.x=lon; + p.y=lat; + return p; + }, + +/* Function to compute latitude, phi3, for the inverse of the Equidistant + Conic projection. +-----------------------------------------------------------------*/ + phi3z: function(ml,e0,e1,e2,e3) { + var phi; + var dphi; + + phi = ml; + for (var i = 0; i < 15; i++) { + dphi = (ml + e1 * Math.sin(2.0 * phi) - e2 * Math.sin(4.0 * phi) + e3 * Math.sin(6.0 * phi))/ e0 - phi; + phi += dphi; + if (Math.abs(dphi) <= .0000000001) { + return phi; + } + } + Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations"); + return null; + } + + +}; \ No newline at end of file diff --git a/src/main/webapp/com/plugins/proj4js/projCode/equi.js b/src/main/webapp/com/plugins/proj4js/projCode/equi.js new file mode 100644 index 0000000..df0c0c1 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/equi.js @@ -0,0 +1,72 @@ +/******************************************************************************* +NAME EQUIRECTANGULAR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Equirectangular projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ +Proj4js.Proj.equi = { + + init: function() { + if(!this.x0) this.x0=0; + if(!this.y0) this.y0=0; + if(!this.lat0) this.lat0=0; + if(!this.long0) this.long0=0; + ///this.t2; + }, + + + +/* Equirectangular forward equations--mapping lat,long to x,y + ---------------------------------------------------------*/ + forward: function(p) { + + var lon=p.x; + var lat=p.y; + + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var x = this.x0 +this. a * dlon *Math.cos(this.lat0); + var y = this.y0 + this.a * lat; + + this.t1=x; + this.t2=Math.cos(this.lat0); + p.x=x; + p.y=y; + return p; + }, //equiFwd() + + + +/* Equirectangular inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ + inverse: function(p) { + + p.x -= this.x0; + p.y -= this.y0; + var lat = p.y /this. a; + + if ( Math.abs(lat) > Proj4js.common.HALF_PI) { + Proj4js.reportError("equi:Inv:DataError"); + } + var lon = Proj4js.common.adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0))); + p.x=lon; + p.y=lat; + }//equiInv() +}; + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/gauss.js b/src/main/webapp/com/plugins/proj4js/projCode/gauss.js new file mode 100644 index 0000000..11adff2 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/gauss.js @@ -0,0 +1,44 @@ + +Proj4js.Proj.gauss = { + + init : function() { + var sphi = Math.sin(this.lat0); + var 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; + var 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; + } +}; + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/gnom.js b/src/main/webapp/com/plugins/proj4js/projCode/gnom.js new file mode 100644 index 0000000..c3cbfdb --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/gnom.js @@ -0,0 +1,117 @@ +/***************************************************************************** +NAME GNOMONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Gnomonic Projection. + Implementation based on the existing sterea and ortho + implementations. + +PROGRAMMER DATE +---------- ---- +Richard Marsden November 2009 + +ALGORITHM REFERENCES + +1. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map + Projections", University of Chicago Press 1993 + +2. Wolfram Mathworld "Gnomonic Projection" + http://mathworld.wolfram.com/GnomonicProjection.html + Accessed: 12th November 2009 +******************************************************************************/ + +Proj4js.Proj.gnom = { + + /* Initialize the Gnomonic projection + -------------------------------------*/ + init: function(def) { + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.sin_p14=Math.sin(this.lat0); + this.cos_p14=Math.cos(this.lat0); + // Approximation for projecting points to the horizon (infinity) + this.infinity_dist = 1000 * this.a; + this.rc = 1; + }, + + + /* Gnomonic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + forward: function(p) { + var sinphi, cosphi; /* sin and cos value */ + var dlon; /* delta longitude value */ + var coslon; /* cos of longitude */ + var ksp; /* scale factor */ + var g; + var x, y; + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + dlon = Proj4js.common.adjust_lon(lon - this.long0); + + sinphi=Math.sin(lat); + cosphi=Math.cos(lat); + + coslon = Math.cos(dlon); + g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; + ksp = 1.0; + if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) { + x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g; + y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g; + } else { + Proj4js.reportError("orthoFwdPointError"); + + // Point is in the opposing hemisphere and is unprojectable + // We still need to return a reasonable point, so we project + // to infinity, on a bearing + // equivalent to the northern hemisphere equivalent + // This is a reasonable approximation for short shapes and lines that + // straddle the horizon. + + x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon); + y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); + + } + p.x=x; + p.y=y; + return p; + }, + + + inverse: function(p) { + var rh; /* Rho */ + var z; /* angle */ + var sinc, cosc; + var c; + var lon , lat; + + /* Inverse equations + -----------------*/ + p.x = (p.x - this.x0) / this.a; + p.y = (p.y - this.y0) / this.a; + + p.x /= this.k0; + p.y /= this.k0; + + if ( (rh = Math.sqrt(p.x * p.x + p.y * p.y)) ) { + c = Math.atan2(rh, this.rc); + sinc = Math.sin(c); + cosc = Math.cos(c); + + lat = Proj4js.common.asinz(cosc*this.sin_p14 + (p.y*sinc*this.cos_p14) / rh); + lon = Math.atan2(p.x*sinc, rh*this.cos_p14*cosc - p.y*this.sin_p14*sinc); + lon = Proj4js.common.adjust_lon(this.long0+lon); + } else { + lat = this.phic0; + lon = 0.0; + } + + p.x=lon; + p.y=lat; + return p; + } +}; + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/gstmerc.js b/src/main/webapp/com/plugins/proj4js/projCode/gstmerc.js new file mode 100644 index 0000000..633c749 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/gstmerc.js @@ -0,0 +1,52 @@ +Proj4js.Proj.gstmerc = { + init : function() { + + // array of: a, b, lon0, lat0, k0, x0, y0 + var temp= this.b / this.a; + this.e= Math.sqrt(1.0 - temp*temp); + this.lc= this.long0; + this.rs= Math.sqrt(1.0+this.e*this.e*Math.pow(Math.cos(this.lat0),4.0)/(1.0-this.e*this.e)); + var sinz= Math.sin(this.lat0); + var pc= Math.asin(sinz/this.rs); + var sinzpc= Math.sin(pc); + this.cp= Proj4js.common.latiso(0.0,pc,sinzpc)-this.rs*Proj4js.common.latiso(this.e,this.lat0,sinz); + this.n2= this.k0*this.a*Math.sqrt(1.0-this.e*this.e)/(1.0-this.e*this.e*sinz*sinz); + this.xs= this.x0; + this.ys= this.y0-this.n2*pc; + + if (!this.title) this.title = "Gauss Schreiber transverse mercator"; + }, + + + // forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + forward : function(p) { + + var lon= p.x; + var lat= p.y; + + var L= this.rs*(lon-this.lc); + var Ls= this.cp+(this.rs*Proj4js.common.latiso(this.e,lat,Math.sin(lat))); + var lat1= Math.asin(Math.sin(L)/Proj4js.common.cosh(Ls)); + var Ls1= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1)); + p.x= this.xs+(this.n2*Ls1); + p.y= this.ys+(this.n2*Math.atan(Proj4js.common.sinh(Ls)/Math.cos(L))); + return p; + }, + + // inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + inverse : function(p) { + + var x= p.x; + var y= p.y; + + var L= Math.atan(Proj4js.common.sinh((x-this.xs)/this.n2)/Math.cos((y-this.ys)/this.n2)); + var lat1= Math.asin(Math.sin((y-this.ys)/this.n2)/Proj4js.common.cosh((x-this.xs)/this.n2)); + var LC= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1)); + p.x= this.lc+L/this.rs; + p.y= Proj4js.common.invlatiso(this.e,(LC-this.cp)/this.rs); + return p; + } + +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/krovak.js b/src/main/webapp/com/plugins/proj4js/projCode/krovak.js new file mode 100644 index 0000000..7ec26d1 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/krovak.js @@ -0,0 +1,135 @@ +/** + NOTES: According to EPSG the full Krovak projection method should have + the following parameters. Within PROJ.4 the azimuth, and pseudo + standard parallel are hardcoded in the algorithm and can't be + altered from outside. The others all have defaults to match the + common usage with Krovak projection. + + lat_0 = latitude of centre of the projection + + lon_0 = longitude of centre of the projection + + ** = azimuth (true) of the centre line passing through the centre of the projection + + ** = latitude of pseudo standard parallel + + k = scale factor on the pseudo standard parallel + + x_0 = False Easting of the centre of the projection at the apex of the cone + + y_0 = False Northing of the centre of the projection at the apex of the cone + + **/ + +Proj4js.Proj.krovak = { + + init: function() { + /* we want Bessel as fixed ellipsoid */ + this.a = 6377397.155; + this.es = 0.006674372230614; + this.e = Math.sqrt(this.es); + /* if latitude of projection center is not set, use 49d30'N */ + if (!this.lat0) { + this.lat0 = 0.863937979737193; + } + if (!this.long0) { + this.long0 = 0.7417649320975901 - 0.308341501185665; + } + /* if scale not set default to 0.9999 */ + if (!this.k0) { + this.k0 = 0.9999; + } + this.s45 = 0.785398163397448; /* 45 */ + this.s90 = 2 * this.s45; + this.fi0 = this.lat0; /* Latitude of projection centre 49 30' */ + /* Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128, + e2=0.006674372230614; + */ + this.e2 = this.es; /* 0.006674372230614; */ + this.e = Math.sqrt(this.e2); + this.alfa = Math.sqrt(1. + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1. - this.e2)); + this.uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */ + this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa); + this.g = Math.pow( (1. + this.e * Math.sin(this.fi0)) / (1. - this.e * Math.sin(this.fi0)) , this.alfa * this.e / 2. ); + this.k = Math.tan( this.u0 / 2. + this.s45) / Math.pow (Math.tan(this.fi0 / 2. + this.s45) , this.alfa) * this.g; + this.k1 = this.k0; + this.n0 = this.a * Math.sqrt(1. - this.e2) / (1. - this.e2 * Math.pow(Math.sin(this.fi0), 2)); + this.s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78 30'00" N */ + this.n = Math.sin(this.s0); + this.ro0 = this.k1 * this.n0 / Math.tan(this.s0); + this.ad = this.s90 - this.uq; + }, + + /* ellipsoid */ + /* calculate xy from lat/lon */ + /* Constants, identical to inverse transform function */ + forward: function(p) { + var gfi, u, deltav, s, d, eps, ro; + var lon = p.x; + var lat = p.y; + var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude + /* Transformation */ + gfi = Math.pow ( ((1. + this.e * Math.sin(lat)) / (1. - this.e * Math.sin(lat))) , (this.alfa * this.e / 2.)); + u= 2. * (Math.atan(this.k * Math.pow( Math.tan(lat / 2. + this.s45), this.alfa) / gfi)-this.s45); + deltav = - delta_lon * this.alfa; + s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav)); + d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s)); + eps = this.n * d; + ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2. + this.s45) , this.n) / Math.pow(Math.tan(s / 2. + this.s45) , this.n); + /* x and y are reverted! */ + //p.y = ro * Math.cos(eps) / a; + //p.x = ro * Math.sin(eps) / a; + p.y = ro * Math.cos(eps) / 1.0; + p.x = ro * Math.sin(eps) / 1.0; + + if(this.czech) { + p.y *= -1.0; + p.x *= -1.0; + } + return (p); + }, + + /* calculate lat/lon from xy */ + inverse: function(p) { + /* Constants, identisch wie in der Umkehrfunktion */ + var u, deltav, s, d, eps, ro, fi1; + var ok; + + /* Transformation */ + /* revert y, x*/ + var tmp = p.x; + p.x=p.y; + p.y=tmp; + if(this.czech) { + p.y *= -1.0; + p.x *= -1.0; + } + ro = Math.sqrt(p.x * p.x + p.y * p.y); + eps = Math.atan2(p.y, p.x); + d = eps / Math.sin(this.s0); + s = 2. * (Math.atan( Math.pow(this.ro0 / ro, 1. / this.n) * Math.tan(this.s0 / 2. + this.s45)) - this.s45); + u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d)); + deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u)); + p.x = this.long0 - deltav / this.alfa; + /* ITERATION FOR lat */ + fi1 = u; + ok = 0; + var iter = 0; + do { + p.y = 2. * ( Math.atan( Math.pow( this.k, -1. / this.alfa) * + Math.pow( Math.tan(u / 2. + this.s45) , 1. / this.alfa) * + Math.pow( (1. + this.e * Math.sin(fi1)) / (1. - this.e * Math.sin(fi1)) , this.e / 2.) + ) - this.s45); + if (Math.abs(fi1 - p.y) < 0.0000000001) ok=1; + fi1 = p.y; + iter += 1; + } while (ok==0 && iter < 15); + if (iter >= 15) { + Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations"); + //console.log('iter:', iter); + return null; + } + + return (p); + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/laea.js b/src/main/webapp/com/plugins/proj4js/projCode/laea.js new file mode 100644 index 0000000..64bd531 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/laea.js @@ -0,0 +1,358 @@ +/******************************************************************************* +NAME LAMBERT AZIMUTHAL EQUAL-AREA + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Azimuthal Equal-Area projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS March, 1991 + +This function was adapted from the Lambert Azimuthal Equal Area projection +code (FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. 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. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.laea = { + S_POLE: 1, + N_POLE: 2, + EQUIT: 3, + OBLIQ: 4, + + +/* Initialize the Lambert Azimuthal Equal Area projection + ------------------------------------------------------*/ + init: function() { + var t = Math.abs(this.lat0); + if (Math.abs(t - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) { + this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE; + } else if (Math.abs(t) < Proj4js.common.EPSLN) { + this.mode = this.EQUIT; + } else { + this.mode = this.OBLIQ; + } + if (this.es > 0) { + var sinphi; + + this.qp = Proj4js.common.qsfnz(this.e, 1.0); + this.mmf = .5 / (1. - this.es); + this.apa = this.authset(this.es); + switch (this.mode) { + case this.N_POLE: + case this.S_POLE: + this.dd = 1.; + break; + case this.EQUIT: + this.rq = Math.sqrt(.5 * this.qp); + this.dd = 1. / this.rq; + this.xmf = 1.; + this.ymf = .5 * this.qp; + break; + case this.OBLIQ: + this.rq = Math.sqrt(.5 * this.qp); + sinphi = Math.sin(this.lat0); + this.sinb1 = Proj4js.common.qsfnz(this.e, sinphi) / this.qp; + this.cosb1 = Math.sqrt(1. - this.sinb1 * this.sinb1); + this.dd = Math.cos(this.lat0) / (Math.sqrt(1. - this.es * sinphi * sinphi) * this.rq * this.cosb1); + this.ymf = (this.xmf = this.rq) / this.dd; + this.xmf *= this.dd; + break; + } + } else { + if (this.mode == this.OBLIQ) { + this.sinph0 = Math.sin(this.lat0); + this.cosph0 = Math.cos(this.lat0); + } + } + }, + +/* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y + -----------------------------------------------------------------------*/ + forward: function(p) { + + /* Forward equations + -----------------*/ + var x,y; + var lam=p.x; + var phi=p.y; + lam = Proj4js.common.adjust_lon(lam - this.long0); + + if (this.sphere) { + var coslam, cosphi, sinphi; + + sinphi = Math.sin(phi); + cosphi = Math.cos(phi); + coslam = Math.cos(lam); + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + y = (this.mode == this.EQUIT) ? 1. + cosphi * coslam : 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam; + if (y <= Proj4js.common.EPSLN) { + Proj4js.reportError("laea:fwd:y less than eps"); + return null; + } + y = Math.sqrt(2. / y); + x = y * cosphi * Math.sin(lam); + y *= (this.mode == this.EQUIT) ? sinphi : this.cosph0 * sinphi - this.sinph0 * cosphi * coslam; + break; + case this.N_POLE: + coslam = -coslam; + case this.S_POLE: + if (Math.abs(phi + this.phi0) < Proj4js.common.EPSLN) { + Proj4js.reportError("laea:fwd:phi < eps"); + return null; + } + y = Proj4js.common.FORTPI - phi * .5; + y = 2. * ((this.mode == this.S_POLE) ? Math.cos(y) : Math.sin(y)); + x = y * Math.sin(lam); + y *= coslam; + break; + } + } else { + var coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; + + coslam = Math.cos(lam); + sinlam = Math.sin(lam); + sinphi = Math.sin(phi); + q = Proj4js.common.qsfnz(this.e, sinphi); + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + sinb = q / this.qp; + cosb = Math.sqrt(1. - sinb * sinb); + } + switch (this.mode) { + case this.OBLIQ: + b = 1. + this.sinb1 * sinb + this.cosb1 * cosb * coslam; + break; + case this.EQUIT: + b = 1. + cosb * coslam; + break; + case this.N_POLE: + b = Proj4js.common.HALF_PI + phi; + q = this.qp - q; + break; + case this.S_POLE: + b = phi - Proj4js.common.HALF_PI; + q = this.qp + q; + break; + } + if (Math.abs(b) < Proj4js.common.EPSLN) { + Proj4js.reportError("laea:fwd:b < eps"); + return null; + } + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + b = Math.sqrt(2. / b); + if (this.mode == this.OBLIQ) { + y = this.ymf * b * (this.cosb1 * sinb - this.sinb1 * cosb * coslam); + } else { + y = (b = Math.sqrt(2. / (1. + cosb * coslam))) * sinb * this.ymf; + } + x = this.xmf * b * cosb * sinlam; + break; + case this.N_POLE: + case this.S_POLE: + if (q >= 0.) { + x = (b = Math.sqrt(q)) * sinlam; + y = coslam * ((this.mode == this.S_POLE) ? b : -b); + } else { + x = y = 0.; + } + break; + } + } + + //v 1.0 + /* + var sin_lat=Math.sin(lat); + var cos_lat=Math.cos(lat); + + var sin_delta_lon=Math.sin(delta_lon); + var cos_delta_lon=Math.cos(delta_lon); + + var g =this.sin_lat_o * sin_lat +this.cos_lat_o * cos_lat * cos_delta_lon; + if (g == -1.0) { + Proj4js.reportError("laea:fwd:Point projects to a circle of radius "+ 2.0 * R); + return null; + } + var ksp = this.a * Math.sqrt(2.0 / (1.0 + g)); + var x = ksp * cos_lat * sin_delta_lon + this.x0; + var y = ksp * (this.cos_lat_o * sin_lat - this.sin_lat_o * cos_lat * cos_delta_lon) + this.y0; + */ + p.x = this.a*x + this.x0; + p.y = this.a*y + this.y0; + return p; + },//lamazFwd() + +/* Inverse equations + -----------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + var x = p.x/this.a; + var y = p.y/this.a; + var lam, phi; + + if (this.sphere) { + var cosz=0.0, rh, sinz=0.0; + + rh = Math.sqrt(x*x + y*y); + phi = rh * .5; + if (phi > 1.) { + Proj4js.reportError("laea:Inv:DataError"); + return null; + } + phi = 2. * Math.asin(phi); + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + sinz = Math.sin(phi); + cosz = Math.cos(phi); + } + switch (this.mode) { + case this.EQUIT: + phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? 0. : Math.asin(y * sinz / rh); + x *= sinz; + y = cosz * rh; + break; + case this.OBLIQ: + phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? this.phi0 : Math.asin(cosz * this.sinph0 + y * sinz * this.cosph0 / rh); + x *= sinz * this.cosph0; + y = (cosz - Math.sin(phi) * this.sinph0) * rh; + break; + case this.N_POLE: + y = -y; + phi = Proj4js.common.HALF_PI - phi; + break; + case this.S_POLE: + phi -= Proj4js.common.HALF_PI; + break; + } + lam = (y == 0. && (this.mode == this.EQUIT || this.mode == this.OBLIQ)) ? 0. : Math.atan2(x, y); + } else { + var cCe, sCe, q, rho, ab=0.0; + + switch (this.mode) { + case this.EQUIT: + case this.OBLIQ: + x /= this.dd; + y *= this.dd; + rho = Math.sqrt(x*x + y*y); + if (rho < Proj4js.common.EPSLN) { + p.x = 0.; + p.y = this.phi0; + return p; + } + sCe = 2. * Math.asin(.5 * rho / this.rq); + cCe = Math.cos(sCe); + x *= (sCe = Math.sin(sCe)); + if (this.mode == this.OBLIQ) { + ab = cCe * this.sinb1 + y * sCe * this.cosb1 / rho + q = this.qp * ab; + y = rho * this.cosb1 * cCe - y * this.sinb1 * sCe; + } else { + ab = y * sCe / rho; + q = this.qp * ab; + y = rho * cCe; + } + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + q = (x * x + y * y); + if (!q ) { + p.x = 0.; + p.y = this.phi0; + return p; + } + /* + q = this.qp - q; + */ + ab = 1. - q / this.qp; + if (this.mode == this.S_POLE) { + ab = - ab; + } + break; + } + lam = Math.atan2(x, y); + phi = this.authlat(Math.asin(ab), this.apa); + } + + /* + var Rh = Math.Math.sqrt(p.x *p.x +p.y * p.y); + var temp = Rh / (2.0 * this.a); + + if (temp > 1) { + Proj4js.reportError("laea:Inv:DataError"); + return null; + } + + var z = 2.0 * Proj4js.common.asinz(temp); + var sin_z=Math.sin(z); + var cos_z=Math.cos(z); + + var lon =this.long0; + if (Math.abs(Rh) > Proj4js.common.EPSLN) { + var lat = Proj4js.common.asinz(this.sin_lat_o * cos_z +this. cos_lat_o * sin_z *p.y / Rh); + var temp =Math.abs(this.lat0) - Proj4js.common.HALF_PI; + if (Math.abs(temp) > Proj4js.common.EPSLN) { + temp = cos_z -this.sin_lat_o * Math.sin(lat); + if(temp!=0.0) lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh)); + } else if (this.lat0 < 0.0) { + lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x,p.y)); + } else { + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y)); + } + } else { + lat = this.lat0; + } + */ + //return(OK); + p.x = Proj4js.common.adjust_lon(this.long0+lam); + p.y = phi; + return p; + },//lamazInv() + +/* determine latitude from authalic latitude */ + P00: .33333333333333333333, + P01: .17222222222222222222, + P02: .10257936507936507936, + P10: .06388888888888888888, + P11: .06640211640211640211, + P20: .01641501294219154443, + + authset: function(es) { + var t; + var APA = new Array(); + APA[0] = es * this.P00; + t = es * es; + APA[0] += t * this.P01; + APA[1] = t * this.P10; + t *= es; + APA[0] += t * this.P02; + APA[1] += t * this.P11; + APA[2] = t * this.P20; + return APA; + }, + + authlat: function(beta, APA) { + var t = beta+beta; + return(beta + APA[0] * Math.sin(t) + APA[1] * Math.sin(t+t) + APA[2] * Math.sin(t+t+t)); + } + +}; + + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/lcc.js b/src/main/webapp/com/plugins/proj4js/projCode/lcc.js new file mode 100644 index 0000000..91c6dc0 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/lcc.js @@ -0,0 +1,148 @@ +/******************************************************************************* +NAME LAMBERT CONFORMAL CONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Lambert Conformal Conic 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 +*******************************************************************************/ + + +//<2104> +proj=lcc +lat_1=10.16666666666667 +lat_0=10.16666666666667 +lon_0=-71.60561777777777 +k_0=1 +x0=-17044 +x0=-23139.97 +ellps=intl +units=m +no_defs no_defs + +// Initialize the Lambert Conformal conic projection +// ----------------------------------------------------------------- + +//Proj4js.Proj.lcc = Class.create(); +Proj4js.Proj.lcc = { + init : function() { + + // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north + //double c_lat; /* center latitude */ + //double c_lon; /* center longitude */ + //double lat1; /* first standard parallel */ + //double lat2; /* second standard parallel */ + //double r_maj; /* major axis */ + //double r_min; /* minor axis */ + //double false_east; /* x offset in meters */ + //double false_north; /* y offset in meters */ + + if (!this.lat2){this.lat2=this.lat0;}//if lat2 is not defined + if (!this.k0) this.k0 = 1.0; + + // Standard Parallels cannot be equal and on opposite sides of the equator + if (Math.abs(this.lat1+this.lat2) < Proj4js.common.EPSLN) { + Proj4js.reportError("lcc:init: Equal Latitudes"); + return; + } + + var temp = this.b / this.a; + this.e = Math.sqrt(1.0 - temp*temp); + + var sin1 = Math.sin(this.lat1); + var cos1 = Math.cos(this.lat1); + var ms1 = Proj4js.common.msfnz(this.e, sin1, cos1); + var ts1 = Proj4js.common.tsfnz(this.e, this.lat1, sin1); + + var sin2 = Math.sin(this.lat2); + var cos2 = Math.cos(this.lat2); + var ms2 = Proj4js.common.msfnz(this.e, sin2, cos2); + var ts2 = Proj4js.common.tsfnz(this.e, this.lat2, sin2); + + var ts0 = Proj4js.common.tsfnz(this.e, this.lat0, Math.sin(this.lat0)); + + if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) { + this.ns = Math.log(ms1/ms2)/Math.log(ts1/ts2); + } else { + this.ns = sin1; + } + this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns)); + this.rh = this.a * this.f0 * Math.pow(ts0, this.ns); + if (!this.title) this.title = "Lambert Conformal Conic"; + }, + + + // Lambert Conformal conic forward equations--mapping lat,long to x,y + // ----------------------------------------------------------------- + forward : function(p) { + + var lon = p.x; + var lat = p.y; + + // convert to radians + if ( lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0) { + //lon = lon * Proj4js.common.D2R; + //lat = lat * Proj4js.common.D2R; + } else { + Proj4js.reportError("lcc:forward: llInputOutOfRange: "+ lon +" : " + lat); + return null; + } + + var con = Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI); + var ts, rh1; + if (con > Proj4js.common.EPSLN) { + ts = Proj4js.common.tsfnz(this.e, lat, Math.sin(lat) ); + rh1 = this.a * this.f0 * Math.pow(ts, this.ns); + } else { + con = lat * this.ns; + if (con <= 0) { + Proj4js.reportError("lcc:forward: No Projection"); + return null; + } + rh1 = 0; + } + var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0); + p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0; + p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0; + + return p; + }, + + // Lambert Conformal Conic inverse equations--mapping x,y to lat/long + // ----------------------------------------------------------------- + inverse : function(p) { + + var rh1, con, ts; + var lat, lon; + var x = (p.x - this.x0)/this.k0; + var y = (this.rh - (p.y - this.y0)/this.k0); + if (this.ns > 0) { + rh1 = Math.sqrt (x * x + y * y); + con = 1.0; + } else { + rh1 = -Math.sqrt (x * x + y * y); + con = -1.0; + } + var theta = 0.0; + if (rh1 != 0) { + theta = Math.atan2((con * x),(con * y)); + } + if ((rh1 != 0) || (this.ns > 0.0)) { + con = 1.0/this.ns; + ts = Math.pow((rh1/(this.a * this.f0)), con); + lat = Proj4js.common.phi2z(this.e, ts); + if (lat == -9999) return null; + } else { + lat = -Proj4js.common.HALF_PI; + } + lon = Proj4js.common.adjust_lon(theta/this.ns + this.long0); + + p.x = lon; + p.y = lat; + return p; + } +}; + + + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/merc.js b/src/main/webapp/com/plugins/proj4js/projCode/merc.js new file mode 100644 index 0000000..8524341 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/merc.js @@ -0,0 +1,115 @@ +/******************************************************************************* +NAME MERCATOR + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS Nov, 1991 +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +//static double r_major = a; /* major axis */ +//static double r_minor = b; /* minor axis */ +//static double lon_center = long0; /* Center longitude (projection center) */ +//static double lat_origin = lat0; /* center latitude */ +//static double e,es; /* eccentricity constants */ +//static double m1; /* small value m */ +//static double false_northing = y0; /* y offset in meters */ +//static double false_easting = x0; /* x offset in meters */ +//scale_fact = k0 + +Proj4js.Proj.merc = { + init : function() { + //?this.temp = this.r_minor / this.r_major; + //this.temp = this.b / this.a; + //this.es = 1.0 - Math.sqrt(this.temp); + //this.e = Math.sqrt( this.es ); + //?this.m1 = Math.cos(this.lat_origin) / (Math.sqrt( 1.0 - this.es * Math.sin(this.lat_origin) * Math.sin(this.lat_origin))); + //this.m1 = Math.cos(0.0) / (Math.sqrt( 1.0 - this.es * Math.sin(0.0) * Math.sin(0.0))); + if (this.lat_ts) { + if (this.sphere) { + this.k0 = Math.cos(this.lat_ts); + } else { + this.k0 = Proj4js.common.msfnz(this.es, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); + } + } + }, + +/* Mercator forward equations--mapping lat,long to x,y + --------------------------------------------------*/ + + forward : function(p) { + //alert("ll2m coords : "+coords); + var lon = p.x; + var lat = p.y; + // convert to radians + if ( lat*Proj4js.common.R2D > 90.0 && + lat*Proj4js.common.R2D < -90.0 && + lon*Proj4js.common.R2D > 180.0 && + lon*Proj4js.common.R2D < -180.0) { + Proj4js.reportError("merc:forward: llInputOutOfRange: "+ lon +" : " + lat); + return null; + } + + var x,y; + if(Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) { + Proj4js.reportError("merc:forward: ll2mAtPoles"); + return null; + } else { + if (this.sphere) { + x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0); + y = this.y0 + this.a * this.k0 * Math.log(Math.tan(Proj4js.common.FORTPI + 0.5*lat)); + } else { + var sinphi = Math.sin(lat); + var ts = Proj4js.common.tsfnz(this.e,lat,sinphi); + x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0); + y = this.y0 - this.a * this.k0 * Math.log(ts); + } + p.x = x; + p.y = y; + return p; + } + }, + + + /* Mercator inverse equations--mapping x,y to lat/long + --------------------------------------------------*/ + inverse : function(p) { + + var x = p.x - this.x0; + var y = p.y - this.y0; + var lon,lat; + + if (this.sphere) { + lat = Proj4js.common.HALF_PI - 2.0 * Math.atan(Math.exp(-y / this.a * this.k0)); + } else { + var ts = Math.exp(-y / (this.a * this.k0)); + lat = Proj4js.common.phi2z(this.e,ts); + if(lat == -9999) { + Proj4js.reportError("merc:inverse: lat = -9999"); + return null; + } + } + lon = Proj4js.common.adjust_lon(this.long0+ x / (this.a * this.k0)); + + p.x = lon; + p.y = lat; + return p; + } +}; + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/mill.js b/src/main/webapp/com/plugins/proj4js/projCode/mill.js new file mode 100644 index 0000000..f954e94 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/mill.js @@ -0,0 +1,68 @@ +/******************************************************************************* +NAME MILLER CYLINDRICAL + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Miller Cylindrical projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan March, 1993 + +This function was adapted from the Lambert Azimuthal Equal Area projection +code (FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. 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. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.mill = { + +/* Initialize the Miller Cylindrical projection + -------------------------------------------*/ + init: function() { + //no-op + }, + + + /* Miller Cylindrical forward equations--mapping lat,long to x,y + ------------------------------------------------------------*/ + forward: function(p) { + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + var dlon = Proj4js.common.adjust_lon(lon -this.long0); + var x = this.x0 + this.a * dlon; + var y = this.y0 + this.a * Math.log(Math.tan((Proj4js.common.PI / 4.0) + (lat / 2.5))) * 1.25; + + p.x=x; + p.y=y; + return p; + },//millFwd() + + /* Miller Cylindrical inverse equations--mapping x,y to lat/long + ------------------------------------------------------------*/ + inverse: function(p) { + p.x -= this.x0; + p.y -= this.y0; + + var lon = Proj4js.common.adjust_lon(this.long0 + p.x /this.a); + var lat = 2.5 * (Math.atan(Math.exp(0.8*p.y/this.a)) - Proj4js.common.PI / 4.0); + + p.x=lon; + p.y=lat; + return p; + }//millInv() +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/moll.js b/src/main/webapp/com/plugins/proj4js/projCode/moll.js new file mode 100644 index 0000000..78b4476 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/moll.js @@ -0,0 +1,100 @@ +/******************************************************************************* +NAME MOLLWEIDE + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the MOllweide projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS May, 1991; Updated Sept, 1992; Updated Feb, 1993 +S. Nelson, EDC Jun, 2993; Made corrections in precision and + number of iterations. + +ALGORITHM REFERENCES + +1. 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. + +2. 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. +*******************************************************************************/ + +Proj4js.Proj.moll = { + + /* Initialize the Mollweide projection + ------------------------------------*/ + init: function(){ + //no-op + }, + + /* Mollweide forward equations--mapping lat,long to x,y + ----------------------------------------------------*/ + forward: function(p) { + + /* Forward equations + -----------------*/ + var lon=p.x; + var lat=p.y; + + var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); + var theta = lat; + var con = Proj4js.common.PI * Math.sin(lat); + + /* Iterate using the Newton-Raphson method to find theta + -----------------------------------------------------*/ + for (var i=0;true;i++) { + var delta_theta = -(theta + Math.sin(theta) - con)/ (1.0 + Math.cos(theta)); + theta += delta_theta; + if (Math.abs(delta_theta) < Proj4js.common.EPSLN) break; + if (i >= 50) { + Proj4js.reportError("moll:Fwd:IterationError"); + //return(241); + } + } + theta /= 2.0; + + /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting" + this is done here because of precision problems with "cos(theta)" + --------------------------------------------------------------------------*/ + if (Proj4js.common.PI/2 - Math.abs(lat) < Proj4js.common.EPSLN) delta_lon =0; + var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0; + var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0; + + p.x=x; + p.y=y; + return p; + }, + + inverse: function(p){ + var theta; + var arg; + + /* Inverse equations + -----------------*/ + p.x-= this.x0; + //~ p.y -= this.y0; + var arg = p.y / (1.4142135623731 * this.a); + + /* Because of division by zero problems, 'arg' can not be 1.0. Therefore + a number very close to one is used instead. + -------------------------------------------------------------------*/ + if(Math.abs(arg) > 0.999999999999) arg=0.999999999999; + var theta =Math.asin(arg); + var lon = Proj4js.common.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta)))); + if(lon < (-Proj4js.common.PI)) lon= -Proj4js.common.PI; + if(lon > Proj4js.common.PI) lon= Proj4js.common.PI; + arg = (2.0 * theta + Math.sin(2.0 * theta)) / Proj4js.common.PI; + if(Math.abs(arg) > 1.0)arg=1.0; + var lat = Math.asin(arg); + //return(OK); + + p.x=lon; + p.y=lat; + return p; + } +}; + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/nzmg.js b/src/main/webapp/com/plugins/proj4js/projCode/nzmg.js new file mode 100644 index 0000000..36560b8 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/nzmg.js @@ -0,0 +1,284 @@ +/******************************************************************************* +NAME NEW ZEALAND MAP GRID + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the New Zealand Map Grid projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + + +ALGORITHM REFERENCES + +1. Department of Land and Survey Technical Circular 1973/32 + http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf + +2. OSG Technical Report 4.1 + http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf + + +IMPLEMENTATION NOTES + +The two references use different symbols for the calculated values. This +implementation uses the variable names similar to the symbols in reference [1]. + +The alogrithm uses different units for delta latitude and delta longitude. +The delta latitude is assumed to be in units of seconds of arc x 10^-5. +The delta longitude is the usual radians. Look out for these conversions. + +The algorithm is described using complex arithmetic. There were three +options: + * find and use a Javascript library for complex arithmetic + * write my own complex library + * expand the complex arithmetic by hand to simple arithmetic + +This implementation has expanded the complex multiplication operations +into parallel simple arithmetic operations for the real and imaginary parts. +The imaginary part is way over to the right of the display; this probably +violates every coding standard in the world, but, to me, it makes it much +more obvious what is going on. + +The following complex operations are used: + - addition + - multiplication + - division + - complex number raised to integer power + - summation + +A summary of complex arithmetic operations: + (from http://en.wikipedia.org/wiki/Complex_arithmetic) + addition: (a + bi) + (c + di) = (a + c) + (b + d)i + subtraction: (a + bi) - (c + di) = (a - c) + (b - d)i + multiplication: (a + bi) x (c + di) = (ac - bd) + (bc + ad)i + division: (a + bi) / (c + di) = [(ac + bd)/(cc + dd)] + [(bc - ad)/(cc + dd)]i + +The algorithm needs to calculate summations of simple and complex numbers. This is +implemented using a for-loop, pre-loading the summed value to zero. + +The algorithm needs to calculate theta^2, theta^3, etc while doing a summation. +There are three possible implementations: + - use Math.pow in the summation loop - except for complex numbers + - precalculate the values before running the loop + - calculate theta^n = theta^(n-1) * theta during the loop +This implementation uses the third option for both real and complex arithmetic. + +For example + psi_n = 1; + sum = 0; + for (n = 1; n <=6; n++) { + psi_n1 = psi_n * psi; // calculate psi^(n+1) + psi_n = psi_n1; + sum = sum + A[n] * psi_n; + } + + +TEST VECTORS + +NZMG E, N: 2487100.638 6751049.719 metres +NZGD49 long, lat: 172.739194 -34.444066 degrees + +NZMG E, N: 2486533.395 6077263.661 metres +NZGD49 long, lat: 172.723106 -40.512409 degrees + +NZMG E, N: 2216746.425 5388508.765 metres +NZGD49 long, lat: 169.172062 -46.651295 degrees + +Note that these test vectors convert from NZMG metres to lat/long referenced +to NZGD49, not the more usual WGS84. The difference is about 70m N/S and about +10m E/W. + +These test vectors are provided in reference [1]. Many more test +vectors are available in + http://www.linz.govt.nz/docs/topography/topographicdata/placenamesdatabase/nznamesmar08.zip +which is a catalog of names on the 260-series maps. + + +EPSG CODES + +NZMG EPSG:27200 +NZGD49 EPSG:4272 + +http://spatialreference.org/ defines these as + Proj4js.defs["EPSG:4272"] = "+proj=longlat +ellps=intl +datum=nzgd49 +no_defs "; + Proj4js.defs["EPSG:27200"] = "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +datum=nzgd49 +units=m +no_defs "; + + +LICENSE + Copyright: Stephen Irons 2008 + Released under terms of the LGPL as per: http://www.gnu.org/copyleft/lesser.html + +*******************************************************************************/ + + +/** + Initialize New Zealand Map Grip projection +*/ + +Proj4js.Proj.nzmg = { + + /** + * iterations: Number of iterations to refine inverse transform. + * 0 -> km accuracy + * 1 -> m accuracy -- suitable for most mapping applications + * 2 -> mm accuracy + */ + iterations: 1, + + init : function() { + this.A = new Array(); + this.A[1] = +0.6399175073; + this.A[2] = -0.1358797613; + this.A[3] = +0.063294409; + this.A[4] = -0.02526853; + this.A[5] = +0.0117879; + this.A[6] = -0.0055161; + this.A[7] = +0.0026906; + this.A[8] = -0.001333; + this.A[9] = +0.00067; + this.A[10] = -0.00034; + + this.B_re = new Array(); this.B_im = new Array(); + this.B_re[1] = +0.7557853228; this.B_im[1] = 0.0; + this.B_re[2] = +0.249204646; this.B_im[2] = +0.003371507; + this.B_re[3] = -0.001541739; this.B_im[3] = +0.041058560; + this.B_re[4] = -0.10162907; this.B_im[4] = +0.01727609; + this.B_re[5] = -0.26623489; this.B_im[5] = -0.36249218; + this.B_re[6] = -0.6870983; this.B_im[6] = -1.1651967; + + this.C_re = new Array(); this.C_im = new Array(); + this.C_re[1] = +1.3231270439; this.C_im[1] = 0.0; + this.C_re[2] = -0.577245789; this.C_im[2] = -0.007809598; + this.C_re[3] = +0.508307513; this.C_im[3] = -0.112208952; + this.C_re[4] = -0.15094762; this.C_im[4] = +0.18200602; + this.C_re[5] = +1.01418179; this.C_im[5] = +1.64497696; + this.C_re[6] = +1.9660549; this.C_im[6] = +2.5127645; + + this.D = new Array(); + this.D[1] = +1.5627014243; + this.D[2] = +0.5185406398; + this.D[3] = -0.03333098; + this.D[4] = -0.1052906; + this.D[5] = -0.0368594; + this.D[6] = +0.007317; + this.D[7] = +0.01220; + this.D[8] = +0.00394; + this.D[9] = -0.0013; + }, + + /** + New Zealand Map Grid Forward - long/lat to x/y + long/lat in radians + */ + forward : function(p) { + var lon = p.x; + var lat = p.y; + + var delta_lat = lat - this.lat0; + var delta_lon = lon - this.long0; + + // 1. Calculate d_phi and d_psi ... // and d_lambda + // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians. + var d_phi = delta_lat / Proj4js.common.SEC_TO_RAD * 1E-5; var d_lambda = delta_lon; + var d_phi_n = 1; // d_phi^0 + + var d_psi = 0; + for (var n = 1; n <= 10; n++) { + d_phi_n = d_phi_n * d_phi; + d_psi = d_psi + this.A[n] * d_phi_n; + } + + // 2. Calculate theta + var th_re = d_psi; var th_im = d_lambda; + + // 3. Calculate z + var th_n_re = 1; var th_n_im = 0; // theta^0 + var th_n_re1; var th_n_im1; + + var z_re = 0; var z_im = 0; + for (var n = 1; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + z_re = z_re + this.B_re[n]*th_n_re - this.B_im[n]*th_n_im; z_im = z_im + this.B_im[n]*th_n_re + this.B_re[n]*th_n_im; + } + + // 4. Calculate easting and northing + p.x = (z_im * this.a) + this.x0; + p.y = (z_re * this.a) + this.y0; + + return p; + }, + + + /** + New Zealand Map Grid Inverse - x/y to long/lat + */ + inverse : function(p) { + + var x = p.x; + var y = p.y; + + var delta_x = x - this.x0; + var delta_y = y - this.y0; + + // 1. Calculate z + var z_re = delta_y / this.a; var z_im = delta_x / this.a; + + // 2a. Calculate theta - first approximation gives km accuracy + var z_n_re = 1; var z_n_im = 0; // z^0 + var z_n_re1; var z_n_im1; + + var th_re = 0; var th_im = 0; + for (var n = 1; n <= 6; n++) { + z_n_re1 = z_n_re*z_re - z_n_im*z_im; z_n_im1 = z_n_im*z_re + z_n_re*z_im; + z_n_re = z_n_re1; z_n_im = z_n_im1; + th_re = th_re + this.C_re[n]*z_n_re - this.C_im[n]*z_n_im; th_im = th_im + this.C_im[n]*z_n_re + this.C_re[n]*z_n_im; + } + + // 2b. Iterate to refine the accuracy of the calculation + // 0 iterations gives km accuracy + // 1 iteration gives m accuracy -- good enough for most mapping applications + // 2 iterations bives mm accuracy + for (var i = 0; i < this.iterations; i++) { + var th_n_re = th_re; var th_n_im = th_im; + var th_n_re1; var th_n_im1; + + var num_re = z_re; var num_im = z_im; + for (var n = 2; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + num_re = num_re + (n-1)*(this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); num_im = num_im + (n-1)*(this.B_im[n]*th_n_re + this.B_re[n]*th_n_im); + } + + th_n_re = 1; th_n_im = 0; + var den_re = this.B_re[1]; var den_im = this.B_im[1]; + for (var n = 2; n <= 6; n++) { + th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im; + th_n_re = th_n_re1; th_n_im = th_n_im1; + den_re = den_re + n * (this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); den_im = den_im + n * (this.B_im[n]*th_n_re + this.B_re[n]*th_n_im); + } + + // Complex division + var den2 = den_re*den_re + den_im*den_im; + th_re = (num_re*den_re + num_im*den_im) / den2; th_im = (num_im*den_re - num_re*den_im) / den2; + } + + // 3. Calculate d_phi ... // and d_lambda + var d_psi = th_re; var d_lambda = th_im; + var d_psi_n = 1; // d_psi^0 + + var d_phi = 0; + for (var n = 1; n <= 9; n++) { + d_psi_n = d_psi_n * d_psi; + d_phi = d_phi + this.D[n] * d_psi_n; + } + + // 4. Calculate latitude and longitude + // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians. + var lat = this.lat0 + (d_phi * Proj4js.common.SEC_TO_RAD * 1E5); + var lon = this.long0 + d_lambda; + + p.x = lon; + p.y = lat; + + return p; + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/omerc.js b/src/main/webapp/com/plugins/proj4js/projCode/omerc.js new file mode 100644 index 0000000..f97085b --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/omerc.js @@ -0,0 +1,256 @@ +/******************************************************************************* +NAME OBLIQUE MERCATOR (HOTINE) + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Oblique Mercator projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +Proj4js.Proj.omerc = { + + /* Initialize the Oblique Mercator projection + ------------------------------------------*/ + init: function() { + if (!this.mode) this.mode=0; + if (!this.lon1) {this.lon1=0;this.mode=1;} + if (!this.lon2) this.lon2=0; + if (!this.lat2) this.lat2=0; + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + var temp = this.b/ this.a; + var es = 1.0 - Math.pow(temp,2); + var e = Math.sqrt(es); + + this.sin_p20=Math.sin(this.lat0); + this.cos_p20=Math.cos(this.lat0); + + this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20; + this.com = Math.sqrt(1.0 - es); + this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es)); + this.al = this.a * this.bl * this.k0 * this.com / this.con; + if (Math.abs(this.lat0) < Proj4js.common.EPSLN) { + this.ts = 1.0; + this.d = 1.0; + this.el = 1.0; + } else { + this.ts = Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20); + this.con = Math.sqrt(this.con); + this.d = this.bl * this.com / (this.cos_p20 * this.con); + if ((this.d * this.d - 1.0) > 0.0) { + if (this.lat0 >= 0.0) { + this.f = this.d + Math.sqrt(this.d * this.d - 1.0); + } else { + this.f = this.d - Math.sqrt(this.d * this.d - 1.0); + } + } else { + this.f = this.d; + } + this.el = this.f * Math.pow(this.ts,this.bl); + } + + //this.longc=52.60353916666667; + + if (this.mode != 0) { + this.g = .5 * (this.f - 1.0/this.f); + this.gama = Proj4js.common.asinz(Math.sin(this.alpha) / this.d); + this.longc= this.longc - Proj4js.common.asinz(this.g * Math.tan(this.gama))/this.bl; + + /* Report parameters common to format B + -------------------------------------*/ + //genrpt(azimuth * R2D,"Azimuth of Central Line: "); + //cenlon(lon_origin); + // cenlat(lat_origin); + + this.con = Math.abs(this.lat0); + if ((this.con > Proj4js.common.EPSLN) && (Math.abs(this.con - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN)) { + this.singam=Math.sin(this.gama); + this.cosgam=Math.cos(this.gama); + + this.sinaz=Math.sin(this.alpha); + this.cosaz=Math.cos(this.alpha); + + if (this.lat0>= 0) { + this.u = (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz); + } else { + this.u = -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz); + } + } else { + Proj4js.reportError("omerc:Init:DataError"); + } + } else { + this.sinphi =Math. sin(this.at1); + this.ts1 = Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi); + this.sinphi = Math.sin(this.lat2); + this.ts2 = Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi); + this.h = Math.pow(this.ts1,this.bl); + this.l = Math.pow(this.ts2,this.bl); + this.f = this.el/this.h; + this.g = .5 * (this.f - 1.0/this.f); + this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h); + this.p = (this.l - this.h) / (this.l + this.h); + this.dlon = this.lon1 - this.lon2; + if (this.dlon < -Proj4js.common.PI) this.lon2 = this.lon2 - 2.0 * Proj4js.common.PI; + if (this.dlon > Proj4js.common.PI) this.lon2 = this.lon2 + 2.0 * Proj4js.common.PI; + this.dlon = this.lon1 - this.lon2; + this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl; + this.dlon = Proj4js.common.adjust_lon(this.lon1 - this.longc); + this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g); + this.alpha = Proj4js.common.asinz(this.d * Math.sin(this.gama)); + + /* Report parameters common to format A + -------------------------------------*/ + + if (Math.abs(this.lat1 - this.lat2) <= Proj4js.common.EPSLN) { + Proj4js.reportError("omercInitDataError"); + //return(202); + } else { + this.con = Math.abs(this.lat1); + } + if ((this.con <= Proj4js.common.EPSLN) || (Math.abs(this.con - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) { + Proj4js.reportError("omercInitDataError"); + //return(202); + } else { + if (Math.abs(Math.abs(this.lat0) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) { + Proj4js.reportError("omercInitDataError"); + //return(202); + } + } + + this.singam=Math.sin(this.gam); + this.cosgam=Math.cos(this.gam); + + this.sinaz=Math.sin(this.alpha); + this.cosaz=Math.cos(this.alpha); + + + if (this.lat0 >= 0) { + this.u = (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz); + } else { + this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz); + } + } + }, + + + /* Oblique Mercator forward equations--mapping lat,long to x,y + ----------------------------------------------------------*/ + forward: function(p) { + var theta; /* angle */ + var sin_phi, cos_phi;/* sin and cos value */ + var b; /* temporary values */ + var c, t, tq; /* temporary values */ + var con, n, ml; /* cone constant, small m */ + var q,us,vl; + var ul,vs; + var s; + var dlon; + var ts1; + + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + sin_phi = Math.sin(lat); + dlon = Proj4js.common.adjust_lon(lon - this.longc); + vl = Math.sin(this.bl * dlon); + if (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN) { + ts1 = Proj4js.common.tsfnz(this.e,lat,sin_phi); + q = this.el / (Math.pow(ts1,this.bl)); + s = .5 * (q - 1.0 / q); + t = .5 * (q + 1.0/ q); + ul = (s * this.singam - vl * this.cosgam) / t; + con = Math.cos(this.bl * dlon); + if (Math.abs(con) < .0000001) { + us = this.al * this.bl * dlon; + } else { + us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl; + if (con < 0) us = us + Proj4js.common.PI * this.al / this.bl; + } + } else { + if (lat >= 0) { + ul = this.singam; + } else { + ul = -this.singam; + } + us = this.al * lat / this.bl; + } + if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) { + //alert("Point projects into infinity","omer-for"); + Proj4js.reportError("omercFwdInfinity"); + //return(205); + } + vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl; + us = us - this.u; + var x = this.x0 + vs * this.cosaz + us * this.sinaz; + var y = this.y0 + us * this.cosaz - vs * this.sinaz; + + p.x=x; + p.y=y; + return p; + }, + + inverse: function(p) { + var delta_lon; /* Delta longitude (Given longitude - center */ + var theta; /* angle */ + var delta_theta; /* adjusted longitude */ + var sin_phi, cos_phi;/* sin and cos value */ + var b; /* temporary values */ + var c, t, tq; /* temporary values */ + var con, n, ml; /* cone constant, small m */ + var vs,us,q,s,ts1; + var vl,ul,bs; + var lon, lat; + var flag; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + flag = 0; + vs = p.x * this.cosaz - p.y * this.sinaz; + us = p.y * this.cosaz + p.x * this.sinaz; + us = us + this.u; + q = Math.exp(-this.bl * vs / this.al); + s = .5 * (q - 1.0/q); + t = .5 * (q + 1.0/q); + vl = Math.sin(this.bl * us / this.al); + ul = (vl * this.cosgam + s * this.singam)/t; + if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) + { + lon = this.longc; + if (ul >= 0.0) { + lat = Proj4js.common.HALF_PI; + } else { + lat = -Proj4js.common.HALF_PI; + } + } else { + con = 1.0 / this.bl; + ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con); + lat = Proj4js.common.phi2z(this.e,ts1); + //if (flag != 0) + //return(flag); + //~ con = Math.cos(this.bl * us /al); + theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl; + lon = Proj4js.common.adjust_lon(theta); + } + p.x=lon; + p.y=lat; + return p; + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/ortho.js b/src/main/webapp/com/plugins/proj4js/projCode/ortho.js new file mode 100644 index 0000000..2f5d088 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/ortho.js @@ -0,0 +1,110 @@ +/******************************************************************************* +NAME ORTHOGRAPHIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Orthographic projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +Proj4js.Proj.ortho = { + + /* Initialize the Orthographic projection + -------------------------------------*/ + init: function(def) { + //double temp; /* temporary variable */ + + /* Place parameters in static storage for common use + -------------------------------------------------*/; + this.sin_p14=Math.sin(this.lat0); + this.cos_p14=Math.cos(this.lat0); + }, + + + /* Orthographic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + forward: function(p) { + var sinphi, cosphi; /* sin and cos value */ + var dlon; /* delta longitude value */ + var coslon; /* cos of longitude */ + var ksp; /* scale factor */ + var g; + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + dlon = Proj4js.common.adjust_lon(lon - this.long0); + + sinphi=Math.sin(lat); + cosphi=Math.cos(lat); + + coslon = Math.cos(dlon); + g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; + ksp = 1.0; + if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) { + var x = this.a * ksp * cosphi * Math.sin(dlon); + var y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); + } else { + Proj4js.reportError("orthoFwdPointError"); + } + p.x=x; + p.y=y; + return p; + }, + + + inverse: function(p) { + var rh; /* height above ellipsoid */ + var z; /* angle */ + var sinz,cosz; /* sin of z and cos of z */ + var temp; + var con; + var lon , lat; + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + rh = Math.sqrt(p.x * p.x + p.y * p.y); + if (rh > this.a + .0000001) { + Proj4js.reportError("orthoInvDataError"); + } + z = Proj4js.common.asinz(rh / this.a); + + sinz=Math.sin(z); + cosz=Math.cos(z); + + lon = this.long0; + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.lat0; + } + lat = Proj4js.common.asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14)/rh); + con = Math.abs(this.lat0) - Proj4js.common.HALF_PI; + if (Math.abs(con) <= Proj4js.common.EPSLN) { + if (this.lat0 >= 0) { + lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y)); + } else { + lon = Proj4js.common.adjust_lon(this.long0 -Math.atan2(-p.x, p.y)); + } + } + con = cosz - this.sin_p14 * Math.sin(lat); + p.x=lon; + p.y=lat; + return p; + } +}; + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/poly.js b/src/main/webapp/com/plugins/proj4js/projCode/poly.js new file mode 100644 index 0000000..52635b3 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/poly.js @@ -0,0 +1,157 @@ +/* Function to compute, phi4, the latitude for the inverse of the + Polyconic projection. +------------------------------------------------------------*/ +function phi4z (eccent,e0,e1,e2,e3,a,b,c,phi) { + var sinphi, sin2ph, tanphi, ml, mlp, con1, con2, con3, dphi, i; + + phi = a; + for (i = 1; i <= 15; i++) { + sinphi = Math.sin(phi); + tanphi = Math.tan(phi); + c = tanphi * Math.sqrt (1.0 - eccent * sinphi * sinphi); + sin2ph = Math.sin (2.0 * phi); + /* + ml = e0 * *phi - e1 * sin2ph + e2 * sin (4.0 * *phi); + mlp = e0 - 2.0 * e1 * cos (2.0 * *phi) + 4.0 * e2 * cos (4.0 * *phi); + */ + ml = e0 * phi - e1 * sin2ph + e2 * Math.sin (4.0 * phi) - e3 * Math.sin (6.0 * phi); + mlp = e0 - 2.0 * e1 * Math.cos (2.0 * phi) + 4.0 * e2 * Math.cos (4.0 * phi) - 6.0 * e3 * Math.cos (6.0 * phi); + con1 = 2.0 * ml + c * (ml * ml + b) - 2.0 * a * (c * ml + 1.0); + con2 = eccent * sin2ph * (ml * ml + b - 2.0 * a * ml) / (2.0 *c); + con3 = 2.0 * (a - ml) * (c * mlp - 2.0 / sin2ph) - 2.0 * mlp; + dphi = con1 / (con2 + con3); + phi += dphi; + if (Math.abs(dphi) <= .0000000001 ) return(phi); + } + Proj4js.reportError("phi4z: No convergence"); + return null; +} + + +/* Function to compute the constant e4 from the input of the eccentricity + of the spheroid, x. This constant is used in the Polar Stereographic + projection. +--------------------------------------------------------------------*/ +function e4fn(x) { + var con, com; + con = 1.0 + x; + com = 1.0 - x; + return (Math.sqrt((Math.pow(con,con))*(Math.pow(com,com)))); +} + + + + + +/******************************************************************************* +NAME POLYCONIC + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Polyconic projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +T. Mittan Mar, 1993 + +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. +*******************************************************************************/ + +Proj4js.Proj.poly = { + + /* Initialize the POLYCONIC projection + ----------------------------------*/ + init: function() { + var temp; /* temporary variable */ + if (this.lat0 == 0) this.lat0 = 90;//this.lat0 ca + + /* Place parameters in static storage for common use + -------------------------------------------------*/ + this.temp = this.b / this.a; + this.es = 1.0 - Math.pow(this.temp,2);// devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles + this.e = Math.sqrt(this.es); + 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 = Proj4js.common.mlfn(this.e0, this.e1,this.e2, this.e3, this.lat0);//si que des zeros le calcul ne se fait pas + //if (!this.ml0) {this.ml0=0;} + }, + + + /* Polyconic forward equations--mapping lat,long to x,y + ---------------------------------------------------*/ + forward: function(p) { + var sinphi, cosphi; /* sin and cos value */ + var al; /* temporary values */ + var c; /* temporary values */ + var con, ml; /* cone constant, small m */ + var ms; /* small m */ + var x,y; + + var lon=p.x; + var lat=p.y; + + con = Proj4js.common.adjust_lon(lon - this.long0); + if (Math.abs(lat) <= .0000001) { + x = this.x0 + this.a * con; + y = this.y0 - this.a * this.ml0; + } else { + sinphi = Math.sin(lat); + cosphi = Math.cos(lat); + + ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); + ms = Proj4js.common.msfnz(this.e,sinphi,cosphi); + con = sinphi; + x = this.x0 + this.a * ms * Math.sin(con)/sinphi; + y = this.y0 + this.a * (ml - this.ml0 + ms * (1.0 - Math.cos(con))/sinphi); + } + + p.x=x; + p.y=y; + return p; + }, + + + /* Inverse equations + -----------------*/ + inverse: function(p) { + var sin_phi, cos_phi; /* sin and cos value */ + var al; /* temporary values */ + var b; /* temporary values */ + var c; /* temporary values */ + var con, ml; /* cone constant, small m */ + var iflg; /* error flag */ + var lon,lat; + p.x -= this.x0; + p.y -= this.y0; + al = this.ml0 + p.y/this.a; + iflg = 0; + + if (Math.abs(al) <= .0000001) { + lon = p.x/this.a + this.long0; + lat = 0.0; + } else { + b = al * al + (p.x/this.a) * (p.x/this.a); + iflg = phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat); + if (iflg != 1) return(iflg); + lon = Proj4js.common.adjust_lon((Proj4js.common.asinz(p.x * c / this.a) / Math.sin(lat)) + this.long0); + } + + p.x=lon; + p.y=lat; + return p; + } +}; + + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/sinu.js b/src/main/webapp/com/plugins/proj4js/projCode/sinu.js new file mode 100644 index 0000000..938a65b --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/sinu.js @@ -0,0 +1,121 @@ +/******************************************************************************* +NAME SINUSOIDAL + +PURPOSE: Transforms input longitude and latitude to Easting and + Northing for the Sinusoidal projection. The + longitude and latitude must be in radians. The Easting + and Northing values will be returned in meters. + +PROGRAMMER DATE +---------- ---- +D. Steinwand, EROS May, 1991 + +This function was adapted from the Sinusoidal projection code (FORTRAN) in the +General Cartographic Transformation Package software which is available from +the U.S. Geological Survey National Mapping Division. + +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. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.sinu = { + + /* Initialize the Sinusoidal projection + ------------------------------------*/ + init: function() { + /* Place parameters in static storage for common use + -------------------------------------------------*/ + + + if (!this.sphere) { + this.en = Proj4js.common.pj_enfn(this.es); + } else { + this.n = 1.; + this.m = 0.; + this.es = 0; + this.C_y = Math.sqrt((this.m + 1.) / this.n); + this.C_x = this.C_y/(this.m + 1.); + } + + }, + + /* Sinusoidal forward equations--mapping lat,long to x,y + -----------------------------------------------------*/ + forward: function(p) { + var x,y,delta_lon; + var lon=p.x; + var lat=p.y; + /* Forward equations + -----------------*/ + lon = Proj4js.common.adjust_lon(lon - this.long0); + + if (this.sphere) { + if (!this.m) { + lat = this.n != 1. ? Math.asin(this.n * Math.sin(lat)): lat; + } else { + var k = this.n * Math.sin(lat); + for (var i = Proj4js.common.MAX_ITER; i ; --i) { + var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat)); + lat -= V; + if (Math.abs(V) < Proj4js.common.EPSLN) break; + } + } + x = this.a * this.C_x * lon * (this.m + Math.cos(lat)); + y = this.a * this.C_y * lat; + + } else { + + var s = Math.sin(lat); + var c = Math.cos(lat); + y = this.a * Proj4js.common.pj_mlfn(lat, s, c, this.en); + x = this.a * lon * c / Math.sqrt(1. - this.es * s * s); + } + + p.x=x; + p.y=y; + return p; + }, + + inverse: function(p) { + var lat,temp,lon; + + /* Inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + lat = p.y / this.a; + + if (this.sphere) { + + p.y /= this.C_y; + lat = this.m ? Math.asin((this.m * p.y + Math.sin(p.y)) / this.n) : + ( this.n != 1. ? Math.asin(Math.sin(p.y) / this.n) : p.y ); + lon = p.x / (this.C_x * (this.m + Math.cos(p.y))); + + } else { + lat = Proj4js.common.pj_inv_mlfn(p.y/this.a, this.es, this.en) + var s = Math.abs(lat); + if (s < Proj4js.common.HALF_PI) { + s = Math.sin(lat); + temp = this.long0 + p.x * Math.sqrt(1. - this.es * s * s) /(this.a * Math.cos(lat)); + //temp = this.long0 + p.x / (this.a * Math.cos(lat)); + lon = Proj4js.common.adjust_lon(temp); + } else if ((s - Proj4js.common.EPSLN) < Proj4js.common.HALF_PI) { + lon = this.long0; + } + + } + + p.x=lon; + p.y=lat; + return p; + } +}; + + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/somerc.js b/src/main/webapp/com/plugins/proj4js/projCode/somerc.js new file mode 100644 index 0000000..a732d46 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/somerc.js @@ -0,0 +1,110 @@ +/******************************************************************************* +NAME SWISS OBLIQUE MERCATOR + +PURPOSE: Swiss projection. +WARNING: X and Y are inverted (weird) in the swiss coordinate system. Not + here, since we want X to be horizontal and Y vertical. + +ALGORITHM REFERENCES +1. "Formules et constantes pour le Calcul pour la + projection cylindrique conforme à axe oblique et pour la transformation entre + des systèmes de référence". + http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf + +*******************************************************************************/ + +Proj4js.Proj.somerc = { + + init: function() { + var phy0 = this.lat0; + this.lambda0 = this.long0; + var sinPhy0 = Math.sin(phy0); + var semiMajorAxis = this.a; + var invF = this.rf; + var flattening = 1 / invF; + var e2 = 2 * flattening - Math.pow(flattening, 2); + var e = this.e = Math.sqrt(e2); + this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2.0)); + this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4.0)); + this.b0 = Math.asin(sinPhy0 / this.alpha); + this.K = Math.log(Math.tan(Math.PI / 4.0 + this.b0 / 2.0)) + - this.alpha + * Math.log(Math.tan(Math.PI / 4.0 + phy0 / 2.0)) + + this.alpha + * e / 2 + * Math.log((1 + e * sinPhy0) + / (1 - e * sinPhy0)); + }, + + + forward: function(p) { + var Sa1 = Math.log(Math.tan(Math.PI / 4.0 - p.y / 2.0)); + var Sa2 = this.e / 2.0 + * Math.log((1 + this.e * Math.sin(p.y)) + / (1 - this.e * Math.sin(p.y))); + var S = -this.alpha * (Sa1 + Sa2) + this.K; + + // spheric latitude + var b = 2.0 * (Math.atan(Math.exp(S)) - Math.PI / 4.0); + + // spheric longitude + var I = this.alpha * (p.x - this.lambda0); + + // psoeudo equatorial rotation + var rotI = Math.atan(Math.sin(I) + / (Math.sin(this.b0) * Math.tan(b) + + Math.cos(this.b0) * Math.cos(I))); + + var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) - + Math.sin(this.b0) * Math.cos(b) * Math.cos(I)); + + p.y = this.R / 2.0 + * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) + + this.y0; + p.x = this.R * rotI + this.x0; + return p; + }, + + inverse: function(p) { + var Y = p.x - this.x0; + var X = p.y - this.y0; + + var rotI = Y / this.R; + var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4.0); + + var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB) + + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI)); + var I = Math.atan(Math.sin(rotI) + / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) + * Math.tan(rotB))); + + var lambda = this.lambda0 + I / this.alpha; + + var S = 0.0; + var phy = b; + var prevPhy = -1000.0; + var iteration = 0; + while (Math.abs(phy - prevPhy) > 0.0000001) + { + if (++iteration > 20) + { + Proj4js.reportError("omercFwdInfinity"); + return; + } + //S = Math.log(Math.tan(Math.PI / 4.0 + phy / 2.0)); + S = 1.0 + / this.alpha + * (Math.log(Math.tan(Math.PI / 4.0 + b / 2.0)) - this.K) + + this.e + * Math.log(Math.tan(Math.PI / 4.0 + + Math.asin(this.e * Math.sin(phy)) + / 2.0)); + prevPhy = phy; + phy = 2.0 * Math.atan(Math.exp(S)) - Math.PI / 2.0; + } + + p.x = lambda; + p.y = phy; + return p; + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/stere.js b/src/main/webapp/com/plugins/proj4js/projCode/stere.js new file mode 100644 index 0000000..399c6e7 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/stere.js @@ -0,0 +1,247 @@ + +// Initialize the Stereographic projection + +Proj4js.Proj.stere = { + ssfn_: function(phit, sinphi, eccen) { + sinphi *= eccen; + return (Math.tan (.5 * (Proj4js.common.HALF_PI + phit)) * Math.pow((1. - sinphi) / (1. + sinphi), .5 * eccen)); + }, + TOL: 1.e-8, + NITER: 8, + CONV: 1.e-10, + S_POLE: 0, + N_POLE: 1, + OBLIQ: 2, + EQUIT: 3, + + init: function() { + this.phits = this.lat_ts ? this.lat_ts : Proj4js.common.HALF_PI; + var t = Math.abs(this.lat0); + if ((Math.abs(t) - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) { + this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE; + } else { + this.mode = t > Proj4js.common.EPSLN ? this.OBLIQ : this.EQUIT; + } + this.phits = Math.abs(this.phits); + if (this.es) { + var X; + + switch (this.mode) { + case this.N_POLE: + case this.S_POLE: + if (Math.abs(this.phits - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) { + this.akm1 = 2. * this.k0 / Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e)); + } else { + t = Math.sin(this.phits); + this.akm1 = Math.cos(this.phits) / Proj4js.common.tsfnz(this.e, this.phits, t); + t *= this.e; + this.akm1 /= Math.sqrt(1. - t * t); + } + break; + case this.EQUIT: + this.akm1 = 2. * this.k0; + break; + case this.OBLIQ: + t = Math.sin(this.lat0); + X = 2. * Math.atan(this.ssfn_(this.lat0, t, this.e)) - Proj4js.common.HALF_PI; + t *= this.e; + this.akm1 = 2. * this.k0 * Math.cos(this.lat0) / Math.sqrt(1. - t * t); + this.sinX1 = Math.sin(X); + this.cosX1 = Math.cos(X); + break; + } + } else { + switch (this.mode) { + case this.OBLIQ: + this.sinph0 = Math.sin(this.lat0); + this.cosph0 = Math.cos(this.lat0); + case this.EQUIT: + this.akm1 = 2. * this.k0; + break; + case this.S_POLE: + case this.N_POLE: + this.akm1 = Math.abs(this.phits - Proj4js.common.HALF_PI) >= Proj4js.common.EPSLN ? + Math.cos(this.phits) / Math.tan(Proj4js.common.FORTPI - .5 * this.phits) : + 2. * this.k0 ; + break; + } + } + }, + +// Stereographic forward equations--mapping lat,long to x,y + forward: function(p) { + var lon = p.x; + lon = Proj4js.common.adjust_lon(lon - this.long0); + var lat = p.y; + var x, y; + + if (this.sphere) { + var sinphi, cosphi, coslam, sinlam; + + sinphi = Math.sin(lat); + cosphi = Math.cos(lat); + coslam = Math.cos(lon); + sinlam = Math.sin(lon); + switch (this.mode) { + case this.EQUIT: + y = 1. + cosphi * coslam; + if (y <= Proj4js.common.EPSLN) { + Proj4js.reportError("stere:forward:Equit"); + } + y = this.akm1 / y; + x = y * cosphi * sinlam; + y *= sinphi; + break; + case this.OBLIQ: + y = 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam; + if (y <= Proj4js.common.EPSLN) { + Proj4js.reportError("stere:forward:Obliq"); + } + y = this.akm1 / y; + x = y * cosphi * sinlam; + y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam; + break; + case this.N_POLE: + coslam = -coslam; + lat = -lat; + //Note no break here so it conitnues through S_POLE + case this.S_POLE: + if (Math.abs(lat - Proj4js.common.HALF_PI) < this.TOL) { + Proj4js.reportError("stere:forward:S_POLE"); + } + y = this.akm1 * Math.tan(Proj4js.common.FORTPI + .5 * lat); + x = sinlam * y; + y *= coslam; + break; + } + } else { + coslam = Math.cos(lon); + sinlam = Math.sin(lon); + sinphi = Math.sin(lat); + var sinX, cosX; + if (this.mode == this.OBLIQ || this.mode == this.EQUIT) { + var Xt = 2. * Math.atan(this.ssfn_(lat, sinphi, this.e)); + sinX = Math.sin(Xt - Proj4js.common.HALF_PI); + cosX = Math.cos(Xt); + } + switch (this.mode) { + case this.OBLIQ: + var A = this.akm1 / (this.cosX1 * (1. + this.sinX1 * sinX + this.cosX1 * cosX * coslam)); + y = A * (this.cosX1 * sinX - this.sinX1 * cosX * coslam); + x = A * cosX; + break; + case this.EQUIT: + var A = 2. * this.akm1 / (1. + cosX * coslam); + y = A * sinX; + x = A * cosX; + break; + case this.S_POLE: + lat = -lat; + coslam = - coslam; + sinphi = -sinphi; + case this.N_POLE: + x = this.akm1 * Proj4js.common.tsfnz(this.e, lat, sinphi); + y = - x * coslam; + break; + } + x = x * sinlam; + } + p.x = x*this.a + this.x0; + p.y = y*this.a + this.y0; + return p; + }, + + +//* Stereographic inverse equations--mapping x,y to lat/long + inverse: function(p) { + var x = (p.x - this.x0)/this.a; /* descale and de-offset */ + var y = (p.y - this.y0)/this.a; + var lon, lat; + + var cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, pi2=0.0; + var i; + + if (this.sphere) { + var c, rh, sinc, cosc; + + rh = Math.sqrt(x*x + y*y); + c = 2. * Math.atan(rh / this.akm1); + sinc = Math.sin(c); + cosc = Math.cos(c); + lon = 0.; + switch (this.mode) { + case this.EQUIT: + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = 0.; + } else { + lat = Math.asin(y * sinc / rh); + } + if (cosc != 0. || x != 0.) lon = Math.atan2(x * sinc, cosc * rh); + break; + case this.OBLIQ: + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.phi0; + } else { + lat = Math.asin(cosc * this.sinph0 + y * sinc * this.cosph0 / rh); + } + c = cosc - this.sinph0 * Math.sin(lat); + if (c != 0. || x != 0.) { + lon = Math.atan2(x * sinc * this.cosph0, c * rh); + } + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + if (Math.abs(rh) <= Proj4js.common.EPSLN) { + lat = this.phi0; + } else { + lat = Math.asin(this.mode == this.S_POLE ? -cosc : cosc); + } + lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y); + break; + } + p.x = Proj4js.common.adjust_lon(lon + this.long0); + p.y = lat; + } else { + rho = Math.sqrt(x*x + y*y); + switch (this.mode) { + case this.OBLIQ: + case this.EQUIT: + tp = 2. * Math.atan2(rho * this.cosX1 , this.akm1); + cosphi = Math.cos(tp); + sinphi = Math.sin(tp); + if( rho == 0.0 ) { + phi_l = Math.asin(cosphi * this.sinX1); + } else { + phi_l = Math.asin(cosphi * this.sinX1 + (y * sinphi * this.cosX1 / rho)); + } + + tp = Math.tan(.5 * (Proj4js.common.HALF_PI + phi_l)); + x *= sinphi; + y = rho * this.cosX1 * cosphi - y * this.sinX1* sinphi; + pi2 = Proj4js.common.HALF_PI; + halfe = .5 * this.e; + break; + case this.N_POLE: + y = -y; + case this.S_POLE: + tp = - rho / this.akm1; + phi_l = Proj4js.common.HALF_PI - 2. * Math.atan(tp); + pi2 = -Proj4js.common.HALF_PI; + halfe = -.5 * this.e; + break; + } + for (i = this.NITER; i--; phi_l = lat) { //check this + sinphi = this.e * Math.sin(phi_l); + lat = 2. * Math.atan(tp * Math.pow((1.+sinphi)/(1.-sinphi), halfe)) - pi2; + if (Math.abs(phi_l - lat) < this.CONV) { + if (this.mode == this.S_POLE) lat = -lat; + lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y); + p.x = Proj4js.common.adjust_lon(lon + this.long0); + p.y = lat; + return p; + } + } + } + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/projCode/sterea.js b/src/main/webapp/com/plugins/proj4js/projCode/sterea.js new file mode 100644 index 0000000..0952956 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/sterea.js @@ -0,0 +1,57 @@ + +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) { + var sinc, cosc, cosl, k; + 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 sinc, cosc, lon, lat, rho; + 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)) ) { + var 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; + } +}; + diff --git a/src/main/webapp/com/plugins/proj4js/projCode/tmerc.js b/src/main/webapp/com/plugins/proj4js/projCode/tmerc.js new file mode 100644 index 0000000..bf68100 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/tmerc.js @@ -0,0 +1,141 @@ +/******************************************************************************* +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 = Proj4js.common.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;true;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() +}; \ No newline at end of file diff --git a/src/main/webapp/com/plugins/proj4js/projCode/utm.js b/src/main/webapp/com/plugins/proj4js/projCode/utm.js new file mode 100644 index 0000000..bed4ea0 --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/utm.js @@ -0,0 +1,43 @@ +/******************************************************************************* +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.utm = { + dependsOn : 'tmerc', + + init : function() { + if (!this.zone) { + Proj4js.reportError("utm:init: zone must be specified for UTM"); + return; + } + this.lat0 = 0.0; + this.long0 = ((6 * Math.abs(this.zone)) - 183) * Proj4js.common.D2R; + this.x0 = 500000.0; + this.y0 = this.utmSouth ? 10000000.0 : 0.0; + this.k0 = 0.9996; + + Proj4js.Proj['tmerc'].init.apply(this); + this.forward = Proj4js.Proj['tmerc'].forward; + this.inverse = Proj4js.Proj['tmerc'].inverse; + } +}; \ No newline at end of file diff --git a/src/main/webapp/com/plugins/proj4js/projCode/vandg.js b/src/main/webapp/com/plugins/proj4js/projCode/vandg.js new file mode 100644 index 0000000..a2c77db --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/projCode/vandg.js @@ -0,0 +1,137 @@ +/******************************************************************************* +NAME VAN DER GRINTEN + +PURPOSE: Transforms input Easting and Northing to longitude and + latitude for the Van der Grinten projection. The + Easting and Northing must be in meters. The longitude + and latitude values will be returned in radians. + +PROGRAMMER DATE +---------- ---- +T. Mittan March, 1993 + +This function was adapted from the Van Der Grinten projection code +(FORTRAN) in the General Cartographic Transformation Package software +which is available from the U.S. Geological Survey National Mapping Division. + +ALGORITHM REFERENCES + +1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, + The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. + +2. 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. + +3. "Software Documentation for GCTP General Cartographic Transformation + Package", U.S. Geological Survey National Mapping Division, May 1982. +*******************************************************************************/ + +Proj4js.Proj.vandg = { + +/* Initialize the Van Der Grinten projection + ----------------------------------------*/ + init: function() { + this.R = 6370997.0; //Radius of earth + }, + + forward: function(p) { + + var lon=p.x; + var lat=p.y; + + /* Forward equations + -----------------*/ + var dlon = Proj4js.common.adjust_lon(lon - this.long0); + var x,y; + + if (Math.abs(lat) <= Proj4js.common.EPSLN) { + x = this.x0 + this.R * dlon; + y = this.y0; + } + var theta = Proj4js.common.asinz(2.0 * Math.abs(lat / Proj4js.common.PI)); + if ((Math.abs(dlon) <= Proj4js.common.EPSLN) || (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) { + x = this.x0; + if (lat >= 0) { + y = this.y0 + Proj4js.common.PI * this.R * Math.tan(.5 * theta); + } else { + y = this.y0 + Proj4js.common.PI * this.R * - Math.tan(.5 * theta); + } + // return(OK); + } + var al = .5 * Math.abs((Proj4js.common.PI / dlon) - (dlon / Proj4js.common.PI)); + var asq = al * al; + var sinth = Math.sin(theta); + var costh = Math.cos(theta); + + var g = costh / (sinth + costh - 1.0); + var gsq = g * g; + var m = g * (2.0 / sinth - 1.0); + var msq = m * m; + var con = Proj4js.common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); + if (dlon < 0) { + con = -con; + } + x = this.x0 + con; + con = Math.abs(con / (Proj4js.common.PI * this.R)); + if (lat >= 0) { + y = this.y0 + Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); + } else { + y = this.y0 - Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); + } + p.x = x; + p.y = y; + return p; + }, + +/* Van Der Grinten inverse equations--mapping x,y to lat/long + ---------------------------------------------------------*/ + inverse: function(p) { + var lon, lat; + var xx,yy,xys,c1,c2,c3; + var al,asq; + var a1; + var m1; + var con; + var th1; + var d; + + /* inverse equations + -----------------*/ + p.x -= this.x0; + p.y -= this.y0; + con = Proj4js.common.PI * this.R; + xx = p.x / con; + yy =p.y / con; + xys = xx * xx + yy * yy; + c1 = -Math.abs(yy) * (1.0 + xys); + c2 = c1 - 2.0 * yy * yy + xx * xx; + c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys; + d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0; + a1 = (c1 - c2 * c2 / 3.0 / c3) / c3; + m1 = 2.0 * Math.sqrt( -a1 / 3.0); + con = ((3.0 * d) / a1) / m1; + if (Math.abs(con) > 1.0) { + if (con >= 0.0) { + con = 1.0; + } else { + con = -1.0; + } + } + th1 = Math.acos(con) / 3.0; + if (p.y >= 0) { + lat = (-m1 *Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI; + } else { + lat = -(-m1 * Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI; + } + + if (Math.abs(xx) < Proj4js.common.EPSLN) { + lon = this.long0; + } + lon = Proj4js.common.adjust_lon(this.long0 + Proj4js.common.PI * (xys - 1.0 + Math.sqrt(1.0 + 2.0 * (xx * xx - yy * yy) + xys * xys)) / 2.0 / xx); + + p.x=lon; + p.y=lat; + return p; + } +}; diff --git a/src/main/webapp/com/plugins/proj4js/util/MGRS.js b/src/main/webapp/com/plugins/proj4js/util/MGRS.js new file mode 100644 index 0000000..c59fa3a --- /dev/null +++ b/src/main/webapp/com/plugins/proj4js/util/MGRS.js @@ -0,0 +1,950 @@ +/* +Portions of this software are based on a port of components from the OpenMap +com.bbn.openmap.proj.coords Java package. An initial port was initially created +by Patrice G. Cappelaere and included in Community Mapbuilder +(http://svn.codehaus.org/mapbuilder/), which is licensed under the LGPL license +as per http://www.gnu.org/copyleft/lesser.html. OpenMap is licensed under the +following license agreement: + + + OpenMap Software License Agreement + ---------------------------------- + +This Agreement sets forth the terms and conditions under which +the software known as OpenMap(tm) will be licensed by BBN +Technologies ("BBN") to you ("Licensee"), and by which Derivative +Works (as hereafter defined) of OpenMap will be licensed by you to BBN. + +Definitions: + + "Derivative Work(s)" shall mean any revision, enhancement, + modification, translation, abridgement, condensation or + expansion created by Licensee or BBN that is based upon the + Software or a portion thereof that would be a copyright + infringement if prepared without the authorization of the + copyright owners of the Software or portion thereof. + + "OpenMap" shall mean a programmer's toolkit for building map + based applications as originally created by BBN, and any + Derivative Works thereof as created by either BBN or Licensee, + but shall include only those Derivative Works BBN has approved + for inclusion into, and BBN has integrated into OpenMap. + + "Standard Version" shall mean OpenMap, as originally created by + BBN. + + "Software" shall mean OpenMap and the Derivative Works created + by Licensee and the collection of files distributed by the + Licensee with OpenMap, and the collection of files created + through textual modifications. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the Derivative Works. + + "Licensee" is you, only if you agree to be bound by the terms + and conditions set forth in this Agreement. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people + involved. + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions that they received it. + +1. BBN maintains all rights, title and interest in and to +OpenMap, including all applicable copyrights, trade secrets, +patents and other intellectual rights therein. Licensee hereby +grants to BBN all right, title and interest into the compilation +of OpenMap. Licensee shall own all rights, title and interest +into the Derivative Works created by Licensee (subject to the +compilation ownership by BBN). + +2. BBN hereby grants to Licensee a royalty free, worldwide right +and license to use, copy, distribute and make Derivative Works of +OpenMap, and sublicensing rights of any of the foregoing in +accordance with the terms and conditions of this Agreement, +provided that you duplicate all of the original copyright notices +and associated disclaimers. + +3. Licensee hereby grants to BBN a royalty free, worldwide right +and license to use, copy, distribute and make Derivative Works of +Derivative Works created by Licensee and sublicensing rights of +any of the foregoing. + +4. Licensee's right to create Derivative Works in the Software is +subject to Licensee agreement to insert a prominent notice in +each changed file stating how and when you changed that file, and +provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise + make them Freely Available, such as by posting said + modifications to Usenet or an equivalent medium, or + placing the modifications on a major archive site and by + providing your modifications to the Copyright Holder. + + b) use the modified Package only within your corporation or + organization. + + c) rename any non-standard executables so the names do not + conflict with standard executables, which must also be + provided, and provide a separate manual page for each + non-standard executable that clearly documents how it + differs from OpenMap. + + d) make other distribution arrangements with the Copyright + Holder. + +5. Licensee may distribute the programs of this Software in +object code or executable form, provided that you do at least ONE +of the following: + + a) distribute an OpenMap version of the executables and + library files, together with instructions (in the manual + page or equivalent) on where to get OpenMap. + + b) accompany the distribution with the machine-readable + source code with your modifications. + + c) accompany any non-standard executables with their + corresponding OpenMap executables, giving the non-standard + executables non-standard names, and clearly documenting + the differences in manual pages (or equivalent), together + with instructions on where to get OpenMap. + + d) make other distribution arrangements with the Copyright + Holder. + +6. You may charge a reasonable copying fee for any distribution +of this Software. You may charge any fee you choose for support +of this Software. You may not charge a fee for this Software +itself. However, you may distribute this Software in aggregate +with other (possibly commercial) programs as part of a larger +(possibly commercial) software distribution provided that you do +not advertise this Software as a product of your own. + +7. The data and images supplied as input to or produced as output +from the Software do not automatically fall under the copyright +of this Software, but belong to whomever generated them, and may +be sold commercially, and may be aggregated with this Software. + +8. BBN makes no representation about the suitability of OpenMap +for any purposes. BBN shall have no duty or requirement to +include any Derivative Works into OpenMap. + +9. Each party hereto represents and warrants that they have the +full unrestricted right to grant all rights and licenses granted +to the other party herein. + +10. THIS PACKAGE IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY +KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND +WITHOUT ANY WARRANTIES AS TO NONINFRINGEMENT. + +11. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE OF DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS CONDUCT, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PACKAGE. + +12. Without limitation of the foregoing, You agree to commit no +act which, directly or indirectly, would violate any U.S. law, +regulation, or treaty, or any other international treaty or +agreement to which the United States adheres or with which the +United States complies, relating to the export or re-export of +any commodities, software, or technical data. +*/ + +if (window.Proj4js && !Proj4js.util) { Proj4js.util = {}; } + +/** + * Converts between lat/lon and MGRS coordinates. Note that this static class + * is restricted to the WGS84 ellipsoid and does not support MGRS notations + * for polar regions (i.e. above 84° North and below 80° South). + * + * If Proj4js is loaded, this will be referenced as Proj4js.util.MGRS. If used + * standalone, it will be referenced as window.MGRS. + * + * @static + */ +(window.Proj4js ? Proj4js.util : window)["MGRS"] = (function() { + + /** + * UTM zones are grouped, and assigned to one of a group of 6 + * sets. + * + * {int} @private + */ + var NUM_100K_SETS = 6; + + /** + * The column letters (for easting) of the lower left value, per + * set. + * + * {string} @private + */ + var SET_ORIGIN_COLUMN_LETTERS = 'AJSAJS'; + + /** + * The row letters (for northing) of the lower left value, per + * set. + * + * {string} @private + */ + var SET_ORIGIN_ROW_LETTERS = 'AFAFAF'; + + var A = 65; // A + var I = 73; // I + var O = 79; // O + var V = 86; // V + var Z = 90; // Z + + /** + * Conversion of lat/lon to MGRS. + * + * @param {object} ll Object literal with lat and lon properties on a + * WGS84 ellipsoid. + * @param {int} accuracy Accuracy in digits (5 for 1 m, 4 for 10 m, 3 for + * 100 m, 4 for 1000 m or 5 for 10000 m). Optional, default is 5. + * @return {string} the MGRS string for the given location and accuracy. + */ + function forward(ll, accuracy) { + accuracy = accuracy || 5; // default accuracy 1m + return encode(LLtoUTM({lat: ll.lat, lon: ll.lon}), accuracy); + } + + /** + * Conversion of MGRS to lat/lon. + * + * @param {string} mgrs MGRS string. + * @return {array} An array with left (longitude), bottom (latitude), right + * (longitude) and top (latitude) values in WGS84, representing the + * bounding box for the provided MGRS reference. + */ + function inverse(mgrs) { + var bbox = UTMtoLL(decode(mgrs.toUpperCase())); + return [bbox.left, bbox.bottom, bbox.right, bbox.top]; + } + + /** + * Conversion from degrees to radians. + * + * @private + * @param {number} deg the angle in degrees. + * @return {number} the angle in radians. + */ + function degToRad(deg) { + return (deg * (Math.PI / 180.0)); + } + + /** + * Conversion from radians to degrees. + * + * @private + * @param {number} rad the angle in radians. + * @return {number} the angle in degrees. + */ + function radToDeg(rad) { + return (180.0 * (rad / Math.PI)); + } + + /** + * Converts a set of Longitude and Latitude co-ordinates to UTM + * using the WGS84 ellipsoid. + * + * @private + * @param {object} ll Object literal with lat and lon properties + * representing the WGS84 coordinate to be converted. + * @return {object} Object literal containing the UTM value with easting, + * northing, zoneNumber and zoneLetter properties, and an optional + * accuracy property in digits. Returns null if the conversion failed. + */ + function LLtoUTM(ll) { + var Lat = ll.lat; + var Long = ll.lon; + var a = 6378137.0; //ellip.radius; + var eccSquared = 0.00669438; //ellip.eccsq; + var k0 = 0.9996; + var LongOrigin; + var eccPrimeSquared; + var N, T, C, A, M; + var LatRad = degToRad(Lat); + var LongRad = degToRad(Long); + var LongOriginRad; + var ZoneNumber; + // (int) + ZoneNumber = Math.floor((Long + 180) / 6) + 1; + + //Make sure the longitude 180.00 is in Zone 60 + if (Long == 180) { + ZoneNumber = 60; + } + + // Special zone for Norway + if (Lat >= 56.0 && Lat < 64.0 && Long >= 3.0 && Long < 12.0) { + ZoneNumber = 32; + } + + // Special zones for Svalbard + if (Lat >= 72.0 && Lat < 84.0) { + if (Long >= 0.0 && Long < 9.0) + ZoneNumber = 31; + else if (Long >= 9.0 && Long < 21.0) + ZoneNumber = 33; + else if (Long >= 21.0 && Long < 33.0) + ZoneNumber = 35; + else if (Long >= 33.0 && Long < 42.0) + ZoneNumber = 37; + } + + LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin + // in middle of + // zone + LongOriginRad = degToRad(LongOrigin); + + eccPrimeSquared = (eccSquared) / (1 - eccSquared); + + N = a / Math.sqrt(1 - eccSquared * Math.sin(LatRad) * Math.sin(LatRad)); + T = Math.tan(LatRad) * Math.tan(LatRad); + C = eccPrimeSquared * Math.cos(LatRad) * Math.cos(LatRad); + A = Math.cos(LatRad) * (LongRad - LongOriginRad); + + M = a + * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 + * eccSquared * eccSquared * eccSquared / 256) + * LatRad + - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared + / 32 + 45 * eccSquared * eccSquared + * eccSquared / 1024) + * Math.sin(2 * LatRad) + + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared + * eccSquared * eccSquared / 1024) + * Math.sin(4 * LatRad) - (35 * eccSquared * eccSquared + * eccSquared / 3072) + * Math.sin(6 * LatRad)); + + var UTMEasting = (k0 + * N + * (A + (1 - T + C) * A * A * A / 6.0 + (5 - 18 * T + T * T + + 72 * C - 58 * eccPrimeSquared) + * A * A * A * A * A / 120.0) + 500000.0); + + var UTMNorthing = (k0 * (M + N + * Math.tan(LatRad) + * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A + / 24.0 + (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) + * A * A * A * A * A * A / 720.0))); + if (Lat < 0.0) { + UTMNorthing += 10000000.0; //10000000 meter offset for + // southern hemisphere + } + + return { + northing: Math.round(UTMNorthing), + easting: Math.round(UTMEasting), + zoneNumber: ZoneNumber, + zoneLetter: getLetterDesignator(Lat) + }; + } + + /** + * Converts UTM coords to lat/long, using the WGS84 ellipsoid. This is a convenience + * class where the Zone can be specified as a single string eg."60N" which + * is then broken down into the ZoneNumber and ZoneLetter. + * + * @private + * @param {object} utm An object literal with northing, easting, zoneNumber + * and zoneLetter properties. If an optional accuracy property is + * provided (in meters), a bounding box will be returned instead of + * latitude and longitude. + * @return {object} An object literal containing either lat and lon values + * (if no accuracy was provided), or top, right, bottom and left values + * for the bounding box calculated according to the provided accuracy. + * Returns null if the conversion failed. + */ + function UTMtoLL(utm) { + + var UTMNorthing = utm.northing; + var UTMEasting = utm.easting; + var zoneLetter = utm.zoneLetter; + var zoneNumber = utm.zoneNumber; + // check the ZoneNummber is valid + if (zoneNumber < 0 || zoneNumber > 60) { + return null; + } + + var k0 = 0.9996; + var a = 6378137.0; //ellip.radius; + var eccSquared = 0.00669438; //ellip.eccsq; + var eccPrimeSquared; + var e1 = (1 - Math.sqrt(1 - eccSquared)) / (1 + Math.sqrt(1 - eccSquared)); + var N1, T1, C1, R1, D, M; + var LongOrigin; + var mu, phi1Rad; + + // remove 500,000 meter offset for longitude + var x = UTMEasting - 500000.0; + var y = UTMNorthing; + + // We must know somehow if we are in the Northern or Southern + // hemisphere, this is the only time we use the letter So even + // if the Zone letter isn't exactly correct it should indicate + // the hemisphere correctly + if (zoneLetter == 'S') { + y -= 10000000.0;// remove 10,000,000 meter offset used + // for southern hemisphere + } + + // There are 60 zones with zone 1 being at West -180 to -174 + LongOrigin = (zoneNumber - 1) * 6 - 180 + 3; // +3 puts origin + // in middle of + // zone + + eccPrimeSquared = (eccSquared) / (1 - eccSquared); + + M = y / k0; + mu = M / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256)); + + phi1Rad = + mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) + * Math.sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.sin(6 * mu); + // double phi1 = ProjMath.radToDeg(phi1Rad); + + N1 = a / Math.sqrt(1 - eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad)); + T1 = Math.tan(phi1Rad) * Math.tan(phi1Rad); + C1 = eccPrimeSquared * Math.cos(phi1Rad) * Math.cos(phi1Rad); + R1 = a * (1 - eccSquared) / Math.pow(1 - eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad), 1.5); + D = x / (N1 * k0); + + var lat = + phi1Rad + - (N1 * Math.tan(phi1Rad) / R1) + * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24 + (61 + 90 + * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) + * D * D * D * D * D * D / 720); + lat = radToDeg(lat); + + var lon = + (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1) + * D * D * D * D * D / 120) / Math.cos(phi1Rad); + lon = LongOrigin + radToDeg(lon); + + var result; + if (utm.accuracy) { + var topRight = UTMtoLL({ + northing: utm.northing + utm.accuracy, + easting: utm.easting + utm.accuracy, + zoneLetter: utm.zoneLetter, + zoneNumber: utm.zoneNumber + }); + result = { + top: topRight.lat, + right: topRight.lon, + bottom: lat, + left: lon + }; + } else { + result = { + lat: lat, + lon: lon + }; + } + return result; + } + + /** + * Calculates the MGRS letter designator for the given latitude. + * + * @private + * @param {number} lat The latitude in WGS84 to get the letter designator + * for. + * @return {char} The letter designator. + */ + function getLetterDesignator(lat) { + //This is here as an error flag to show that the Latitude is + //outside MGRS limits + var LetterDesignator = 'Z'; + + if ((84 >= lat) && (lat >= 72)) + LetterDesignator = 'X'; + else if ((72 > lat) && (lat >= 64)) + LetterDesignator = 'W'; + else if ((64 > lat) && (lat >= 56)) + LetterDesignator = 'V'; + else if ((56 > lat) && (lat >= 48)) + LetterDesignator = 'U'; + else if ((48 > lat) && (lat >= 40)) + LetterDesignator = 'T'; + else if ((40 > lat) && (lat >= 32)) + LetterDesignator = 'S'; + else if ((32 > lat) && (lat >= 24)) + LetterDesignator = 'R'; + else if ((24 > lat) && (lat >= 16)) + LetterDesignator = 'Q'; + else if ((16 > lat) && (lat >= 8)) + LetterDesignator = 'P'; + else if ((8 > lat) && (lat >= 0)) + LetterDesignator = 'N'; + else if ((0 > lat) && (lat >= -8)) + LetterDesignator = 'M'; + else if ((-8 > lat) && (lat >= -16)) + LetterDesignator = 'L'; + else if ((-16 > lat) && (lat >= -24)) + LetterDesignator = 'K'; + else if ((-24 > lat) && (lat >= -32)) + LetterDesignator = 'J'; + else if ((-32 > lat) && (lat >= -40)) + LetterDesignator = 'H'; + else if ((-40 > lat) && (lat >= -48)) + LetterDesignator = 'G'; + else if ((-48 > lat) && (lat >= -56)) + LetterDesignator = 'F'; + else if ((-56 > lat) && (lat >= -64)) + LetterDesignator = 'E'; + else if ((-64 > lat) && (lat >= -72)) + LetterDesignator = 'D'; + else if ((-72 > lat) && (lat >= -80)) + LetterDesignator = 'C'; + return LetterDesignator; + } + + /** + * Encodes a UTM location as MGRS string. + * + * @private + * @param {object} utm An object literal with easting, northing, + * zoneLetter, zoneNumber + * @param {number} accuracy Accuracy in digits (1-5). + * @return {string} MGRS string for the given UTM location. + */ + function encode(utm, accuracy) { + var seasting = "" + utm.easting, + snorthing = "" + utm.northing; + + return utm.zoneNumber + utm.zoneLetter + + get100kID(utm.easting, utm.northing, utm.zoneNumber) + + seasting.substr(seasting.length - 5, accuracy) + + snorthing.substr(snorthing.length - 5, accuracy); + } + + /** + * Get the two letter 100k designator for a given UTM easting, + * northing and zone number value. + * + * @private + * @param {number} easting + * @param {number} northing + * @param {number} zoneNumber + * @return the two letter 100k designator for the given UTM location. + */ + function get100kID(easting, northing, zoneNumber) { + var setParm = get100kSetForZone(zoneNumber); + var setColumn = Math.floor(easting / 100000); + var setRow = Math.floor(northing / 100000) % 20; + return getLetter100kID(setColumn, setRow, setParm); + } + + /** + * Given a UTM zone number, figure out the MGRS 100K set it is in. + * + * @private + * @param {number} i An UTM zone number. + * @return {number} the 100k set the UTM zone is in. + */ + function get100kSetForZone(i) { + var setParm = i % NUM_100K_SETS; + if (setParm == 0) + setParm = NUM_100K_SETS; + + return setParm; + } + + /** + * Get the two-letter MGRS 100k designator given information + * translated from the UTM northing, easting and zone number. + * + * @private + * @param {number} column the column index as it relates to the MGRS + * 100k set spreadsheet, created from the UTM easting. + * Values are 1-8. + * @param {number} row the row index as it relates to the MGRS 100k set + * spreadsheet, created from the UTM northing value. Values + * are from 0-19. + * @param {number} parm the set block, as it relates to the MGRS 100k set + * spreadsheet, created from the UTM zone. Values are from + * 1-60. + * @return two letter MGRS 100k code. + */ + function getLetter100kID(column, row, parm) { + // colOrigin and rowOrigin are the letters at the origin of the set + var index = parm-1; + var colOrigin = SET_ORIGIN_COLUMN_LETTERS.charCodeAt(index); + var rowOrigin = SET_ORIGIN_ROW_LETTERS.charCodeAt(index); + + // colInt and rowInt are the letters to build to return + var colInt = colOrigin + column - 1; + var rowInt = rowOrigin + row; + var rollover = false; + + if ( colInt > Z ) { + colInt = colInt - Z + A - 1; + rollover = true; + } + + if (colInt == I || (colOrigin < I && colInt > I) + || ((colInt > I || colOrigin < I) && rollover)) { + colInt++; + } + + if (colInt == O || (colOrigin < O && colInt > O) + || ((colInt > O || colOrigin < O) && rollover)) { + colInt++; + + if (colInt == I) { + colInt++; + } + } + + if (colInt > Z) { + colInt = colInt - Z + A - 1; + } + + if (rowInt > V) { + rowInt = rowInt - V + A - 1; + rollover = true; + } else { + rollover = false; + } + + if( ((rowInt == I) || ((rowOrigin < I) && (rowInt > I))) + || (((rowInt > I)||(rowOrigin < I)) && rollover)) { + rowInt++; + } + + if( ((rowInt == O) || ((rowOrigin < O) && (rowInt > O))) + || (((rowInt > O)|| (rowOrigin < O)) && rollover)) { + rowInt++; + + if (rowInt == I) { + rowInt++; + } + } + + if (rowInt > V) { + rowInt = rowInt - V + A - 1; + } + + var twoLetter = String.fromCharCode(colInt) + String.fromCharCode(rowInt); + return twoLetter; + } + + /** + * Decode the UTM parameters from a MGRS string. + * + * @private + * @param {string} mgrsString an UPPERCASE coordinate string is expected. + * @return {object} An object literal with easting, northing, zoneLetter, + * zoneNumber and accuracy (in meters) properties. + */ + function decode(mgrsString) { + + if (mgrsString == null || mgrsString.length == 0) { + throw("MGRSPoint coverting from nothing"); + } + + var length = mgrsString.length; + + var hunK = null; + var sb = ""; + var testChar; + var i = 0; + + // get Zone number + while (!(/[A-Z]/).test(testChar = mgrsString.charAt(i))) { + if (i >= 2) { + throw("MGRSPoint bad conversion from: " + + mgrsString); + } + sb += testChar; + i++; + } + + var zoneNumber = parseInt(sb, 10); + + if (i == 0 || i + 3 > length) { + // A good MGRS string has to be 4-5 digits long, + // ##AAA/#AAA at least. + throw("MGRSPoint bad conversion from: " + + mgrsString); + } + + var zoneLetter = mgrsString.charAt(i++); + + // Should we check the zone letter here? Why not. + if (zoneLetter <= 'A' || zoneLetter == 'B' || zoneLetter == 'Y' + || zoneLetter >= 'Z' || zoneLetter == 'I' + || zoneLetter == 'O') { + throw("MGRSPoint zone letter " + + zoneLetter + " not handled: " + mgrsString); + } + + hunK = mgrsString.substring(i, i += 2); + + var set = get100kSetForZone(zoneNumber); + + var east100k = getEastingFromChar(hunK.charAt(0), set); + var north100k = getNorthingFromChar(hunK.charAt(1), set); + + // We have a bug where the northing may be 2000000 too low. + // How + // do we know when to roll over? + + while (north100k < getMinNorthing(zoneLetter)) { + north100k += 2000000; + } + + // calculate the char index for easting/northing separator + var remainder = length - i; + + if (remainder % 2 != 0) { + throw("MGRSPoint has to have an even number \nof digits after the zone letter and two 100km letters - front \nhalf for easting meters, second half for \nnorthing meters" + + mgrsString); + } + + var sep = remainder / 2; + + var sepEasting = 0.0; + var sepNorthing = 0.0; + + if (sep > 0) { + var accuracyBonus = 100000.0 / Math.pow(10, sep); + var sepEastingString = mgrsString.substring(i, i + sep); + sepEasting = parseFloat(sepEastingString) * accuracyBonus; + var sepNorthingString = mgrsString.substring(i + sep); + sepNorthing = parseFloat(sepNorthingString) * accuracyBonus; + } + + easting = sepEasting + east100k; + northing = sepNorthing + north100k; + + return { + easting: easting, + northing: northing, + zoneLetter: zoneLetter, + zoneNumber: zoneNumber, + accuracy: accuracyBonus + }; + } + + /** + * Given the first letter from a two-letter MGRS 100k zone, and given the + * MGRS table set for the zone number, figure out the easting value that + * should be added to the other, secondary easting value. + * + * @private + * @param {char} e The first letter from a two-letter MGRS 100´k zone. + * @param {number} set The MGRS table set for the zone number. + * @return {number} The easting value for the given letter and set. + */ + function getEastingFromChar(e, set) { + // colOrigin is the letter at the origin of the set for the + // column + var curCol = SET_ORIGIN_COLUMN_LETTERS.charCodeAt(set - 1); + var eastingValue = 100000.0; + var rewindMarker = false; + + while (curCol != e.charCodeAt(0)) { + curCol++; + if (curCol == I) + curCol++; + if (curCol == O) + curCol++; + if (curCol > Z) { + if (rewindMarker) { + throw("Bad character: " + e); + } + curCol = A; + rewindMarker = true; + } + eastingValue += 100000.0; + } + + return eastingValue; + } + + /** + * Given the second letter from a two-letter MGRS 100k zone, and given the + * MGRS table set for the zone number, figure out the northing value that + * should be added to the other, secondary northing value. You have to + * remember that Northings are determined from the equator, and the vertical + * cycle of letters mean a 2000000 additional northing meters. This happens + * approx. every 18 degrees of latitude. This method does *NOT* count any + * additional northings. You have to figure out how many 2000000 meters need + * to be added for the zone letter of the MGRS coordinate. + * + * @private + * @param {char} n Second letter of the MGRS 100k zone + * @param {number} set The MGRS table set number, which is dependent on the + * UTM zone number. + * @return {number} The northing value for the given letter and set. + */ + function getNorthingFromChar(n, set) { + + if (n > 'V') { + throw("MGRSPoint given invalid Northing " + + n); + } + + // rowOrigin is the letter at the origin of the set for the + // column + var curRow = SET_ORIGIN_ROW_LETTERS.charCodeAt(set - 1); + var northingValue = 0.0; + var rewindMarker = false; + + while (curRow != n.charCodeAt(0)) { + curRow++; + if (curRow == I) + curRow++; + if (curRow == O) + curRow++; + // fixing a bug making whole application hang in this loop + // when 'n' is a wrong character + if (curRow > V) { + if (rewindMarker) { // making sure that this loop ends + throw("Bad character: " + n); + } + curRow = A; + rewindMarker = true; + } + northingValue += 100000.0; + } + + return northingValue; + } + + /** + * The function getMinNorthing returns the minimum northing value of a MGRS + * zone. + * + * Ported from Geotrans' c Lattitude_Band_Value structure table. + * + * @private + * @param {char} zoneLetter The MGRS zone to get the min northing for. + * @return {number} + */ + function getMinNorthing(zoneLetter) { + var northing; + switch (zoneLetter) { + case 'C': + northing = 1100000.0; + break; + case 'D': + northing = 2000000.0; + break; + case 'E': + northing = 2800000.0; + break; + case 'F': + northing = 3700000.0; + break; + case 'G': + northing = 4600000.0; + break; + case 'H': + northing = 5500000.0; + break; + case 'J': + northing = 6400000.0; + break; + case 'K': + northing = 7300000.0; + break; + case 'L': + northing = 8200000.0; + break; + case 'M': + northing = 9100000.0; + break; + case 'N': + northing = 0.0; + break; + case 'P': + northing = 800000.0; + break; + case 'Q': + northing = 1700000.0; + break; + case 'R': + northing = 2600000.0; + break; + case 'S': + northing = 3500000.0; + break; + case 'T': + northing = 4400000.0; + break; + case 'U': + northing = 5300000.0; + break; + case 'V': + northing = 6200000.0; + break; + case 'W': + northing = 7000000.0; + break; + case 'X': + northing = 7900000.0; + break; + default: + northing = -1.0; + } + if (northing >= 0.0) { + return northing; + } else { + throw("Invalid zone letter: " + + zoneLetter); + } + + } + + return { + forward: forward, + inverse: inverse + }; + +})(); + +if (window.Proj4js && Proj4js.Point) { + + /** + * Creates a Proj4js.Point instance from a MGRS reference. The point will + * reference the center of the MGRS reference, and coordinates will be in + * WGS84 longitude and latitude. + * + * Only available if Proj4js is loaded. + * + * @param mgrs {string} MGRS reference + */ + Proj4js.Point.fromMGRS = function(mgrs) { + var llbbox = Proj4js.util.MGRS.inverse(mgrs); + return new Proj4js.Point( + (llbbox[2] + llbbox[0]) / 2, + (llbbox[3] + llbbox[1]) / 2 + ); + }; + + /** + * Converts a Proj4js.Point instance to a MGRS reference. The point + * coordinates are expected to be in WGS84 longitude and latitude. + * + * Only available if Proj4js is loaded. + * + * @param accuracy {int} The accuracy for the MGRS reference in digits (5 + * for 1 m, 4 for 10 m, 3 for 100 m, 4 for 1000 m or 5 for 10000 m) + */ + Proj4js.Point.prototype.toMGRS = function(accuracy) { + return Proj4js.util.MGRS.forward({lon: this.x, lat: this.y}, accuracy); + }; + +} diff --git a/target/classes/egovframework/mapper/sgis/map/MapMainMapper.xml b/target/classes/egovframework/mapper/sgis/map/MapMainMapper.xml index fe4e173..e496b63 100644 --- a/target/classes/egovframework/mapper/sgis/map/MapMainMapper.xml +++ b/target/classes/egovframework/mapper/sgis/map/MapMainMapper.xml @@ -54,4 +54,464 @@ ORDER BY HOL_COD ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/target/classes/sgis/map/mapper/MapMainMapper.class b/target/classes/sgis/map/mapper/MapMainMapper.class index 9c686be..a1f1473 100644 Binary files a/target/classes/sgis/map/mapper/MapMainMapper.class and b/target/classes/sgis/map/mapper/MapMainMapper.class differ diff --git a/target/classes/sgis/map/service/MapMainService.class b/target/classes/sgis/map/service/MapMainService.class index 26b8676..4b981bf 100644 Binary files a/target/classes/sgis/map/service/MapMainService.class and b/target/classes/sgis/map/service/MapMainService.class differ diff --git a/target/classes/sgis/map/service/impl/MapMainServiceImpl.class b/target/classes/sgis/map/service/impl/MapMainServiceImpl.class index 2289244..ff226b0 100644 Binary files a/target/classes/sgis/map/service/impl/MapMainServiceImpl.class and b/target/classes/sgis/map/service/impl/MapMainServiceImpl.class differ diff --git a/target/classes/sgis/map/web/MapMainController.class b/target/classes/sgis/map/web/MapMainController.class index e2f0f5f..8cf95e2 100644 Binary files a/target/classes/sgis/map/web/MapMainController.class and b/target/classes/sgis/map/web/MapMainController.class differ diff --git a/target/m2e-wtp/web-resources/META-INF/maven/smart_ground/sgis/pom.properties b/target/m2e-wtp/web-resources/META-INF/maven/smart_ground/sgis/pom.properties index 1af5e36..8d6eb74 100644 --- a/target/m2e-wtp/web-resources/META-INF/maven/smart_ground/sgis/pom.properties +++ b/target/m2e-wtp/web-resources/META-INF/maven/smart_ground/sgis/pom.properties @@ -1,5 +1,5 @@ #Generated by Maven Integration for Eclipse -#Sun Jun 22 02:05:59 KST 2025 +#Sun Jun 22 23:42:03 KST 2025 version=1.0.0 groupId=smart_ground m2e.projectName=sgis