```  1 /**
2  * The built-in projections.
3  *
4  * @see pv.Geo.Projection
5  * @namespace
6  */
7 pv.Geo.projections = {
8
9   /** @see http://en.wikipedia.org/wiki/Mercator_projection */
10   mercator: {
11     project: function(latlng) {
12       return {
13           x: latlng.lng / 180,
14           y: latlng.lat > 85 ? 1 : latlng.lat < -85 ? -1
15               : Math.log(Math.tan(Math.PI / 4
16               + pv.radians(latlng.lat) / 2)) / Math.PI
17         };
18     },
19     invert: function(xy) {
20       return {
21           lng: xy.x * 180,
22           lat: pv.degrees(2 * Math.atan(Math.exp(xy.y * Math.PI)) - Math.PI / 2)
23         };
24     }
25   },
26
27   /** @see http://en.wikipedia.org/wiki/Gall-Peters_projection */
28   "gall-peters": {
29     project: function(latlng) {
30       return {
31           x: latlng.lng / 180,
33         };
34     },
35     invert: function(xy) {
36       return {
37           lng: xy.x * 180,
38           lat: pv.degrees(Math.asin(xy.y))
39         };
40     }
41   },
42
43   /** @see http://en.wikipedia.org/wiki/Sinusoidal_projection */
44   sinusoidal: {
45     project: function(latlng) {
46       return {
48           y: latlng.lat / 90
49         };
50     },
51     invert: function(xy) {
52       return {
53           lng: pv.degrees((xy.x * Math.PI) / Math.cos(xy.y * Math.PI / 2)),
54           lat: xy.y * 90
55         };
56     }
57   },
58
59   /** @see http://en.wikipedia.org/wiki/Aitoff_projection */
60   aitoff: {
61     project: function(latlng) {
64           a = Math.acos(Math.cos(f) * Math.cos(l / 2));
65       return {
66           x: 2 * (a ? (Math.cos(f) * Math.sin(l / 2) * a / Math.sin(a)) : 0) / Math.PI,
67           y: 2 * (a ? (Math.sin(f) * a / Math.sin(a)) : 0) / Math.PI
68         };
69     },
70     invert: function(xy) {
71       var x = xy.x * Math.PI / 2,
72           y = xy.y * Math.PI / 2;
73       return {
74           lng: pv.degrees(x / Math.cos(y)),
75           lat: pv.degrees(y)
76         };
77     }
78   },
79
80   /** @see http://en.wikipedia.org/wiki/Hammer_projection */
81   hammer: {
82     project: function(latlng) {
85           c = Math.sqrt(1 + Math.cos(f) * Math.cos(l / 2));
86       return {
87           x: 2 * Math.SQRT2 * Math.cos(f) * Math.sin(l / 2) / c / 3,
88           y: Math.SQRT2 * Math.sin(f) / c / 1.5
89         };
90     },
91     invert: function(xy) {
92       var x = xy.x * 3,
93           y = xy.y * 1.5,
94           z = Math.sqrt(1 - x * x / 16 - y * y / 4);
95       return {
96           lng: pv.degrees(2 * Math.atan2(z * x, 2 * (2 * z * z - 1))),
97           lat: pv.degrees(Math.asin(z * y))
98         };
99     }
100   },
101
102   /** The identity or "none" projection. */
103   identity: {
104     project: function(latlng) {
105       return {
106           x: latlng.lng / 180,
107           y: latlng.lat / 90
108         };
109     },
110     invert: function(xy) {
111       return {
112           lng: xy.x * 180,
113           lat: xy.y * 90
114         };
115     }
116   }
117 };
118 ```