1
/*******************************************************************************
2
NAME OBLIQUE MERCATOR (HOTINE)
4
PURPOSE: Transforms input longitude and latitude to Easting and
5
Northing for the Oblique Mercator projection. The
6
longitude and latitude must be in radians. The Easting
7
and Northing values will be returned in meters.
15
1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
16
Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
17
State Government Printing Office, Washington D.C., 1987.
19
2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
20
U.S. Geological Survey Professional Paper 1453 , United State Government
21
Printing Office, Washington D.C., 1989.
22
*******************************************************************************/
24
Proj4js.Proj.omerc = {
26
/* Initialize the Oblique Mercator projection
27
------------------------------------------*/
29
if (!this.mode) this.mode=0;
30
if (!this.lon1) {this.lon1=0;this.mode=1;}
31
if (!this.lon2) this.lon2=0;
32
if (!this.lat2) this.lat2=0;
34
/* Place parameters in static storage for common use
35
-------------------------------------------------*/
36
var temp = this.b/ this.a;
37
var es = 1.0 - Math.pow(temp,2);
38
var e = Math.sqrt(es);
40
this.sin_p20=Math.sin(this.lat0);
41
this.cos_p20=Math.cos(this.lat0);
43
this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20;
44
this.com = Math.sqrt(1.0 - es);
45
this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es));
46
this.al = this.a * this.bl * this.k0 * this.com / this.con;
47
if (Math.abs(this.lat0) < Proj4js.common.EPSLN) {
52
this.ts = Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20);
53
this.con = Math.sqrt(this.con);
54
this.d = this.bl * this.com / (this.cos_p20 * this.con);
55
if ((this.d * this.d - 1.0) > 0.0) {
56
if (this.lat0 >= 0.0) {
57
this.f = this.d + Math.sqrt(this.d * this.d - 1.0);
59
this.f = this.d - Math.sqrt(this.d * this.d - 1.0);
64
this.el = this.f * Math.pow(this.ts,this.bl);
67
//this.longc=52.60353916666667;
70
this.g = .5 * (this.f - 1.0/this.f);
71
this.gama = Proj4js.common.asinz(Math.sin(this.alpha) / this.d);
72
this.longc= this.longc - Proj4js.common.asinz(this.g * Math.tan(this.gama))/this.bl;
74
/* Report parameters common to format B
75
-------------------------------------*/
76
//genrpt(azimuth * R2D,"Azimuth of Central Line: ");
78
// cenlat(lat_origin);
80
this.con = Math.abs(this.lat0);
81
if ((this.con > Proj4js.common.EPSLN) && (Math.abs(this.con - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN)) {
82
this.singam=Math.sin(this.gama);
83
this.cosgam=Math.cos(this.gama);
85
this.sinaz=Math.sin(this.alpha);
86
this.cosaz=Math.cos(this.alpha);
89
this.u = (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
91
this.u = -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
94
Proj4js.reportError("omerc:Init:DataError");
97
this.sinphi =Math. sin(this.at1);
98
this.ts1 = Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi);
99
this.sinphi = Math.sin(this.lat2);
100
this.ts2 = Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi);
101
this.h = Math.pow(this.ts1,this.bl);
102
this.l = Math.pow(this.ts2,this.bl);
103
this.f = this.el/this.h;
104
this.g = .5 * (this.f - 1.0/this.f);
105
this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h);
106
this.p = (this.l - this.h) / (this.l + this.h);
107
this.dlon = this.lon1 - this.lon2;
108
if (this.dlon < -Proj4js.common.PI) this.lon2 = this.lon2 - 2.0 * Proj4js.common.PI;
109
if (this.dlon > Proj4js.common.PI) this.lon2 = this.lon2 + 2.0 * Proj4js.common.PI;
110
this.dlon = this.lon1 - this.lon2;
111
this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl;
112
this.dlon = Proj4js.common.adjust_lon(this.lon1 - this.longc);
113
this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g);
114
this.alpha = Proj4js.common.asinz(this.d * Math.sin(this.gama));
116
/* Report parameters common to format A
117
-------------------------------------*/
119
if (Math.abs(this.lat1 - this.lat2) <= Proj4js.common.EPSLN) {
120
Proj4js.reportError("omercInitDataError");
123
this.con = Math.abs(this.lat1);
125
if ((this.con <= Proj4js.common.EPSLN) || (Math.abs(this.con - HALF_PI) <= Proj4js.common.EPSLN)) {
126
Proj4js.reportError("omercInitDataError");
129
if (Math.abs(Math.abs(this.lat0) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) {
130
Proj4js.reportError("omercInitDataError");
135
this.singam=Math.sin(this.gam);
136
this.cosgam=Math.cos(this.gam);
138
this.sinaz=Math.sin(this.alpha);
139
this.cosaz=Math.cos(this.alpha);
142
if (this.lat0 >= 0) {
143
this.u = (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
145
this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
151
/* Oblique Mercator forward equations--mapping lat,long to x,y
152
----------------------------------------------------------*/
153
forward: function(p) {
154
var theta; /* angle */
155
var sin_phi, cos_phi;/* sin and cos value */
156
var b; /* temporary values */
157
var c, t, tq; /* temporary values */
158
var con, n, ml; /* cone constant, small m */
169
sin_phi = Math.sin(lat);
170
dlon = Proj4js.common.adjust_lon(lon - this.longc);
171
vl = Math.sin(this.bl * dlon);
172
if (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN) {
173
ts1 = Proj4js.common.tsfnz(this.e,lat,sin_phi);
174
q = this.el / (Math.pow(ts1,this.bl));
175
s = .5 * (q - 1.0 / q);
176
t = .5 * (q + 1.0/ q);
177
ul = (s * this.singam - vl * this.cosgam) / t;
178
con = Math.cos(this.bl * dlon);
179
if (Math.abs(con) < .0000001) {
180
us = this.al * this.bl * dlon;
182
us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl;
183
if (con < 0) us = us + Proj4js.common.PI * this.al / this.bl;
191
us = this.al * lat / this.bl;
193
if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) {
194
//alert("Point projects into infinity","omer-for");
195
Proj4js.reportError("omercFwdInfinity");
198
vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl;
200
var x = this.x0 + vs * this.cosaz + us * this.sinaz;
201
var y = this.y0 + us * this.cosaz - vs * this.sinaz;
208
inverse: function(p) {
209
var delta_lon; /* Delta longitude (Given longitude - center */
210
var theta; /* angle */
211
var delta_theta; /* adjusted longitude */
212
var sin_phi, cos_phi;/* sin and cos value */
213
var b; /* temporary values */
214
var c, t, tq; /* temporary values */
215
var con, n, ml; /* cone constant, small m */
226
vs = p.x * this.cosaz - p.y * this.sinaz;
227
us = p.y * this.cosaz + p.x * this.sinaz;
229
q = Math.exp(-this.bl * vs / this.al);
230
s = .5 * (q - 1.0/q);
231
t = .5 * (q + 1.0/q);
232
vl = Math.sin(this.bl * us / this.al);
233
ul = (vl * this.cosgam + s * this.singam)/t;
234
if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN)
238
lat = Proj4js.common.HALF_PI;
240
lat = -Proj4js.common.HALF_PI;
244
ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con);
245
lat = Proj4js.common.phi2z(this.e,ts1);
248
//~ con = Math.cos(this.bl * us /al);
249
theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl;
250
lon = Proj4js.common.adjust_lon(theta);