leancloud-storage
Version:
LeanCloud JavaScript SDK.
190 lines (159 loc) • 5.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
var _ = require('underscore');
/*global navigator: false */
module.exports = function (AV) {
/**
* Creates a new GeoPoint with any of the following forms:<br>
* @example
* new GeoPoint(otherGeoPoint)
* new GeoPoint(30, 30)
* new GeoPoint([30, 30])
* new GeoPoint({latitude: 30, longitude: 30})
* new GeoPoint() // defaults to (0, 0)
* @class
*
* <p>Represents a latitude / longitude point that may be associated
* with a key in a AVObject or used as a reference point for geo queries.
* This allows proximity-based queries on the key.</p>
*
* <p>Only one key in a class may contain a GeoPoint.</p>
*
* <p>Example:<pre>
* var point = new AV.GeoPoint(30.0, -20.0);
* var object = new AV.Object("PlaceObject");
* object.set("location", point);
* object.save();</pre></p>
*/
AV.GeoPoint = function (arg1, arg2) {
if (_.isArray(arg1)) {
AV.GeoPoint._validate(arg1[0], arg1[1]);
this.latitude = arg1[0];
this.longitude = arg1[1];
} else if (_.isObject(arg1)) {
AV.GeoPoint._validate(arg1.latitude, arg1.longitude);
this.latitude = arg1.latitude;
this.longitude = arg1.longitude;
} else if (_.isNumber(arg1) && _.isNumber(arg2)) {
AV.GeoPoint._validate(arg1, arg2);
this.latitude = arg1;
this.longitude = arg2;
} else {
this.latitude = 0;
this.longitude = 0;
} // Add properties so that anyone using Webkit or Mozilla will get an error
// if they try to set values that are out of bounds.
var self = this;
if (this.__defineGetter__ && this.__defineSetter__) {
// Use _latitude and _longitude to actually store the values, and add
// getters and setters for latitude and longitude.
this._latitude = this.latitude;
this._longitude = this.longitude;
this.__defineGetter__('latitude', function () {
return self._latitude;
});
this.__defineGetter__('longitude', function () {
return self._longitude;
});
this.__defineSetter__('latitude', function (val) {
AV.GeoPoint._validate(val, self.longitude);
self._latitude = val;
});
this.__defineSetter__('longitude', function (val) {
AV.GeoPoint._validate(self.latitude, val);
self._longitude = val;
});
}
};
/**
* @lends AV.GeoPoint.prototype
* @property {float} latitude North-south portion of the coordinate, in range
* [-90, 90]. Throws an exception if set out of range in a modern browser.
* @property {float} longitude East-west portion of the coordinate, in range
* [-180, 180]. Throws if set out of range in a modern browser.
*/
/**
* Throws an exception if the given lat-long is out of bounds.
* @private
*/
AV.GeoPoint._validate = function (latitude, longitude) {
if (latitude < -90.0) {
throw new Error('AV.GeoPoint latitude ' + latitude + ' < -90.0.');
}
if (latitude > 90.0) {
throw new Error('AV.GeoPoint latitude ' + latitude + ' > 90.0.');
}
if (longitude < -180.0) {
throw new Error('AV.GeoPoint longitude ' + longitude + ' < -180.0.');
}
if (longitude > 180.0) {
throw new Error('AV.GeoPoint longitude ' + longitude + ' > 180.0.');
}
};
/**
* Creates a GeoPoint with the user's current location, if available.
* @return {Promise.<AV.GeoPoint>}
*/
AV.GeoPoint.current = function () {
return new _promise.default(function (resolve, reject) {
navigator.geolocation.getCurrentPosition(function (location) {
resolve(new AV.GeoPoint({
latitude: location.coords.latitude,
longitude: location.coords.longitude
}));
}, reject);
});
};
_.extend(AV.GeoPoint.prototype,
/** @lends AV.GeoPoint.prototype */
{
/**
* Returns a JSON representation of the GeoPoint, suitable for AV.
* @return {Object}
*/
toJSON: function toJSON() {
AV.GeoPoint._validate(this.latitude, this.longitude);
return {
__type: 'GeoPoint',
latitude: this.latitude,
longitude: this.longitude
};
},
/**
* Returns the distance from this GeoPoint to another in radians.
* @param {AV.GeoPoint} point the other AV.GeoPoint.
* @return {Number}
*/
radiansTo: function radiansTo(point) {
var d2r = Math.PI / 180.0;
var lat1rad = this.latitude * d2r;
var long1rad = this.longitude * d2r;
var lat2rad = point.latitude * d2r;
var long2rad = point.longitude * d2r;
var deltaLat = lat1rad - lat2rad;
var deltaLong = long1rad - long2rad;
var sinDeltaLatDiv2 = Math.sin(deltaLat / 2);
var sinDeltaLongDiv2 = Math.sin(deltaLong / 2); // Square of half the straight line chord distance between both points.
var a = sinDeltaLatDiv2 * sinDeltaLatDiv2 + Math.cos(lat1rad) * Math.cos(lat2rad) * sinDeltaLongDiv2 * sinDeltaLongDiv2;
a = Math.min(1.0, a);
return 2 * Math.asin(Math.sqrt(a));
},
/**
* Returns the distance from this GeoPoint to another in kilometers.
* @param {AV.GeoPoint} point the other AV.GeoPoint.
* @return {Number}
*/
kilometersTo: function kilometersTo(point) {
return this.radiansTo(point) * 6371.0;
},
/**
* Returns the distance from this GeoPoint to another in miles.
* @param {AV.GeoPoint} point the other AV.GeoPoint.
* @return {Number}
*/
milesTo: function milesTo(point) {
return this.radiansTo(point) * 3958.8;
}
});
};