UNPKG

5.8 kBJavaScriptView Raw
1'use strict';
2
3var _promise = require('babel-runtime/core-js/promise');
4
5var _promise2 = _interopRequireDefault(_promise);
6
7function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
9var _ = require('underscore');
10
11/*global navigator: false */
12module.exports = function (AV) {
13 /**
14 * Creates a new GeoPoint with any of the following forms:<br>
15 * @example
16 * new GeoPoint(otherGeoPoint)
17 * new GeoPoint(30, 30)
18 * new GeoPoint([30, 30])
19 * new GeoPoint({latitude: 30, longitude: 30})
20 * new GeoPoint() // defaults to (0, 0)
21 * @class
22 *
23 * <p>Represents a latitude / longitude point that may be associated
24 * with a key in a AVObject or used as a reference point for geo queries.
25 * This allows proximity-based queries on the key.</p>
26 *
27 * <p>Only one key in a class may contain a GeoPoint.</p>
28 *
29 * <p>Example:<pre>
30 * var point = new AV.GeoPoint(30.0, -20.0);
31 * var object = new AV.Object("PlaceObject");
32 * object.set("location", point);
33 * object.save();</pre></p>
34 */
35 AV.GeoPoint = function (arg1, arg2) {
36 if (_.isArray(arg1)) {
37 AV.GeoPoint._validate(arg1[0], arg1[1]);
38 this.latitude = arg1[0];
39 this.longitude = arg1[1];
40 } else if (_.isObject(arg1)) {
41 AV.GeoPoint._validate(arg1.latitude, arg1.longitude);
42 this.latitude = arg1.latitude;
43 this.longitude = arg1.longitude;
44 } else if (_.isNumber(arg1) && _.isNumber(arg2)) {
45 AV.GeoPoint._validate(arg1, arg2);
46 this.latitude = arg1;
47 this.longitude = arg2;
48 } else {
49 this.latitude = 0;
50 this.longitude = 0;
51 }
52
53 // Add properties so that anyone using Webkit or Mozilla will get an error
54 // if they try to set values that are out of bounds.
55 var self = this;
56 if (this.__defineGetter__ && this.__defineSetter__) {
57 // Use _latitude and _longitude to actually store the values, and add
58 // getters and setters for latitude and longitude.
59 this._latitude = this.latitude;
60 this._longitude = this.longitude;
61 this.__defineGetter__('latitude', function () {
62 return self._latitude;
63 });
64 this.__defineGetter__('longitude', function () {
65 return self._longitude;
66 });
67 this.__defineSetter__('latitude', function (val) {
68 AV.GeoPoint._validate(val, self.longitude);
69 self._latitude = val;
70 });
71 this.__defineSetter__('longitude', function (val) {
72 AV.GeoPoint._validate(self.latitude, val);
73 self._longitude = val;
74 });
75 }
76 };
77
78 /**
79 * @lends AV.GeoPoint.prototype
80 * @property {float} latitude North-south portion of the coordinate, in range
81 * [-90, 90]. Throws an exception if set out of range in a modern browser.
82 * @property {float} longitude East-west portion of the coordinate, in range
83 * [-180, 180]. Throws if set out of range in a modern browser.
84 */
85
86 /**
87 * Throws an exception if the given lat-long is out of bounds.
88 * @private
89 */
90 AV.GeoPoint._validate = function (latitude, longitude) {
91 if (latitude < -90.0) {
92 throw new Error('AV.GeoPoint latitude ' + latitude + ' < -90.0.');
93 }
94 if (latitude > 90.0) {
95 throw new Error('AV.GeoPoint latitude ' + latitude + ' > 90.0.');
96 }
97 if (longitude < -180.0) {
98 throw new Error('AV.GeoPoint longitude ' + longitude + ' < -180.0.');
99 }
100 if (longitude > 180.0) {
101 throw new Error('AV.GeoPoint longitude ' + longitude + ' > 180.0.');
102 }
103 };
104
105 /**
106 * Creates a GeoPoint with the user's current location, if available.
107 * @return {Promise.<AV.GeoPoint>}
108 */
109 AV.GeoPoint.current = function () {
110 return new _promise2.default(function (resolve, reject) {
111 navigator.geolocation.getCurrentPosition(function (location) {
112 resolve(new AV.GeoPoint({
113 latitude: location.coords.latitude,
114 longitude: location.coords.longitude
115 }));
116 }, reject);
117 });
118 };
119
120 _.extend(AV.GeoPoint.prototype,
121 /** @lends AV.GeoPoint.prototype */{
122 /**
123 * Returns a JSON representation of the GeoPoint, suitable for AV.
124 * @return {Object}
125 */
126 toJSON: function toJSON() {
127 AV.GeoPoint._validate(this.latitude, this.longitude);
128 return {
129 __type: 'GeoPoint',
130 latitude: this.latitude,
131 longitude: this.longitude
132 };
133 },
134
135 /**
136 * Returns the distance from this GeoPoint to another in radians.
137 * @param {AV.GeoPoint} point the other AV.GeoPoint.
138 * @return {Number}
139 */
140 radiansTo: function radiansTo(point) {
141 var d2r = Math.PI / 180.0;
142 var lat1rad = this.latitude * d2r;
143 var long1rad = this.longitude * d2r;
144 var lat2rad = point.latitude * d2r;
145 var long2rad = point.longitude * d2r;
146 var deltaLat = lat1rad - lat2rad;
147 var deltaLong = long1rad - long2rad;
148 var sinDeltaLatDiv2 = Math.sin(deltaLat / 2);
149 var sinDeltaLongDiv2 = Math.sin(deltaLong / 2);
150 // Square of half the straight line chord distance between both points.
151 var a = sinDeltaLatDiv2 * sinDeltaLatDiv2 + Math.cos(lat1rad) * Math.cos(lat2rad) * sinDeltaLongDiv2 * sinDeltaLongDiv2;
152 a = Math.min(1.0, a);
153 return 2 * Math.asin(Math.sqrt(a));
154 },
155
156 /**
157 * Returns the distance from this GeoPoint to another in kilometers.
158 * @param {AV.GeoPoint} point the other AV.GeoPoint.
159 * @return {Number}
160 */
161 kilometersTo: function kilometersTo(point) {
162 return this.radiansTo(point) * 6371.0;
163 },
164
165 /**
166 * Returns the distance from this GeoPoint to another in miles.
167 * @param {AV.GeoPoint} point the other AV.GeoPoint.
168 * @return {Number}
169 */
170 milesTo: function milesTo(point) {
171 return this.radiansTo(point) * 3958.8;
172 }
173 });
174};
\No newline at end of file