1 | /******************************************************************************* |
---|
2 | NAME SWISS OBLIQUE MERCATOR |
---|
3 | |
---|
4 | PURPOSE: Swiss projection. |
---|
5 | WARNING: X and Y are inverted (weird) in the swiss coordinate system. Not |
---|
6 | here, since we want X to be horizontal and Y vertical. |
---|
7 | |
---|
8 | ALGORITHM REFERENCES |
---|
9 | 1. "Formules et constantes pour le Calcul pour la |
---|
10 | projection cylindrique conforme à axe oblique et pour la transformation entre |
---|
11 | des systÚmes de référence". |
---|
12 | http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf |
---|
13 | |
---|
14 | *******************************************************************************/ |
---|
15 | |
---|
16 | Proj4js.Proj.somerc = { |
---|
17 | |
---|
18 | init: function() { |
---|
19 | var phy0 = this.lat0; |
---|
20 | this.lambda0 = this.long0; |
---|
21 | var sinPhy0 = Math.sin(phy0); |
---|
22 | var semiMajorAxis = this.a; |
---|
23 | var invF = this.rf; |
---|
24 | var flattening = 1 / invF; |
---|
25 | var e2 = 2 * flattening - Math.pow(flattening, 2); |
---|
26 | var e = this.e = Math.sqrt(e2); |
---|
27 | this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2.0)); |
---|
28 | this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4.0)); |
---|
29 | this.b0 = Math.asin(sinPhy0 / this.alpha); |
---|
30 | this.K = Math.log(Math.tan(Math.PI / 4.0 + this.b0 / 2.0)) |
---|
31 | - this.alpha |
---|
32 | * Math.log(Math.tan(Math.PI / 4.0 + phy0 / 2.0)) |
---|
33 | + this.alpha |
---|
34 | * e / 2 |
---|
35 | * Math.log((1 + e * sinPhy0) |
---|
36 | / (1 - e * sinPhy0)); |
---|
37 | }, |
---|
38 | |
---|
39 | |
---|
40 | forward: function(p) { |
---|
41 | var Sa1 = Math.log(Math.tan(Math.PI / 4.0 - p.y / 2.0)); |
---|
42 | var Sa2 = this.e / 2.0 |
---|
43 | * Math.log((1 + this.e * Math.sin(p.y)) |
---|
44 | / (1 - this.e * Math.sin(p.y))); |
---|
45 | var S = -this.alpha * (Sa1 + Sa2) + this.K; |
---|
46 | |
---|
47 | // spheric latitude |
---|
48 | var b = 2.0 * (Math.atan(Math.exp(S)) - Math.PI / 4.0); |
---|
49 | |
---|
50 | // spheric longitude |
---|
51 | var I = this.alpha * (p.x - this.lambda0); |
---|
52 | |
---|
53 | // psoeudo equatorial rotation |
---|
54 | var rotI = Math.atan(Math.sin(I) |
---|
55 | / (Math.sin(this.b0) * Math.tan(b) + |
---|
56 | Math.cos(this.b0) * Math.cos(I))); |
---|
57 | |
---|
58 | var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) - |
---|
59 | Math.sin(this.b0) * Math.cos(b) * Math.cos(I)); |
---|
60 | |
---|
61 | p.y = this.R / 2.0 |
---|
62 | * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) |
---|
63 | + this.y0; |
---|
64 | p.x = this.R * rotI + this.x0; |
---|
65 | return p; |
---|
66 | }, |
---|
67 | |
---|
68 | inverse: function(p) { |
---|
69 | var Y = p.x - this.x0; |
---|
70 | var X = p.y - this.y0; |
---|
71 | |
---|
72 | var rotI = Y / this.R; |
---|
73 | var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4.0); |
---|
74 | |
---|
75 | var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB) |
---|
76 | + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI)); |
---|
77 | var I = Math.atan(Math.sin(rotI) |
---|
78 | / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) |
---|
79 | * Math.tan(rotB))); |
---|
80 | |
---|
81 | var lambda = this.lambda0 + I / this.alpha; |
---|
82 | |
---|
83 | var S = 0.0; |
---|
84 | var phy = b; |
---|
85 | var prevPhy = -1000.0; |
---|
86 | var iteration = 0; |
---|
87 | while (Math.abs(phy - prevPhy) > 0.0000001) |
---|
88 | { |
---|
89 | if (++iteration > 20) |
---|
90 | { |
---|
91 | Proj4js.reportError("omercFwdInfinity"); |
---|
92 | return; |
---|
93 | } |
---|
94 | //S = Math.log(Math.tan(Math.PI / 4.0 + phy / 2.0)); |
---|
95 | S = 1.0 |
---|
96 | / this.alpha |
---|
97 | * (Math.log(Math.tan(Math.PI / 4.0 + b / 2.0)) - this.K) |
---|
98 | + this.e |
---|
99 | * Math.log(Math.tan(Math.PI / 4.0 |
---|
100 | + Math.asin(this.e * Math.sin(phy)) |
---|
101 | / 2.0)); |
---|
102 | prevPhy = phy; |
---|
103 | phy = 2.0 * Math.atan(Math.exp(S)) - Math.PI / 2.0; |
---|
104 | } |
---|
105 | |
---|
106 | p.x = lambda; |
---|
107 | p.y = phy; |
---|
108 | return p; |
---|
109 | } |
---|
110 | }; |
---|