/*******************************************************************************
|
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;
|
}
|
};
|