You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
349 lines
11 KiB
JavaScript
349 lines
11 KiB
JavaScript
2 years ago
|
console.log("%c p5.geolocation Loaded ", "color:pink; background:black; ");
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Check if location services are available
|
||
|
*
|
||
|
* Returns true if geolocation is available
|
||
|
*
|
||
|
* @method locationCheck
|
||
|
* @return {boolean} true if geolocation is available
|
||
|
*/
|
||
|
p5.prototype.geoCheck = function(){
|
||
|
if (navigator.geolocation) {
|
||
|
return true;
|
||
|
}else{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get User's Current Position
|
||
|
*
|
||
|
* Gets the users current position. Can be used in preload(), or as a callback.
|
||
|
*
|
||
|
* @method getCurrentPosition
|
||
|
* @param {function} a callback to handle the current position data
|
||
|
* @param {function} a callback to handle an error
|
||
|
* @return {object} an object containing the users position data
|
||
|
*/
|
||
|
p5.prototype.getCurrentPosition = function(callback, errorCallback) {
|
||
|
|
||
|
var ret = {};
|
||
|
var self = this;
|
||
|
|
||
|
// if (navigator.geolocation) {
|
||
|
if (true){
|
||
|
navigator.geolocation.getCurrentPosition(success, geoError);
|
||
|
}else{
|
||
|
geoError("geolocation not available");
|
||
|
};
|
||
|
|
||
|
function geoError(message){
|
||
|
console.log(message.message);
|
||
|
ret.error = message.message;
|
||
|
if(typeof errorCallback == 'function'){ errorCallback(message.message) };
|
||
|
}
|
||
|
|
||
|
function success(position){
|
||
|
console.log(position);
|
||
|
|
||
|
//get the entire position object....
|
||
|
// //see the p5.js github libraries wiki page for more info on what is going on here.
|
||
|
// for(var k in position){
|
||
|
// if (typeof position[k] == 'object'){
|
||
|
// ret[k] = {};
|
||
|
// for(var x in position[k]){
|
||
|
// ret[k][x] = position[k][x];
|
||
|
// }
|
||
|
// } else {
|
||
|
// ret[k] = position[k];
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
//get only the coords part of the position object
|
||
|
for(var x in position.coords){
|
||
|
ret[x] = position.coords[x];
|
||
|
ret['timestamp'] = position.timestamp;
|
||
|
}
|
||
|
if (typeof self._decrementPreload === 'function') { self._decrementPreload() };
|
||
|
if(typeof callback == 'function'){ callback(position.coords) };
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
};
|
||
|
|
||
|
//add the get Current position to the preload stack.
|
||
|
p5.prototype.registerPreloadMethod('getCurrentPosition', p5.prototype);
|
||
|
|
||
|
/**
|
||
|
* Get User's Current Position on an interval
|
||
|
*
|
||
|
* Gets the users current position on an interval. Can be useful if watchPosition is not responsive enough. This can be a resource hog (read:battery) as it is calling the getPosition at the rate of your interval. Set it long for less intense usage.
|
||
|
*
|
||
|
* @method getCurrentPosition
|
||
|
* @param {function} a callback to handle the current position data
|
||
|
* @param {function} an interval in MS
|
||
|
* @param {function} a callback to handle an error
|
||
|
*/
|
||
|
p5.prototype._intervalPosition = null;
|
||
|
p5.prototype.intervalCurrentPosition = function(callback, interval, errorCallback){
|
||
|
|
||
|
var gogogadget = 5000;
|
||
|
gogogadget = interval;
|
||
|
|
||
|
if (navigator.geolocation) {
|
||
|
|
||
|
_intervalPosition = setInterval(function(){
|
||
|
|
||
|
console.log("pos");
|
||
|
navigator.geolocation.getCurrentPosition(success, geoError);
|
||
|
|
||
|
}, gogogadget)
|
||
|
|
||
|
}else{
|
||
|
geoError("geolocation not available");
|
||
|
};
|
||
|
|
||
|
function geoError(message){
|
||
|
console.log(message.message);
|
||
|
if(typeof errorCallback == 'function'){ errorCallback(message.message) };
|
||
|
}
|
||
|
|
||
|
function success(position){
|
||
|
if(typeof callback == 'function'){ callback(position.coords) };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear interval Position
|
||
|
*
|
||
|
* clears the current intervalCurrentPosition()
|
||
|
*
|
||
|
* @method clearIntervalPos()
|
||
|
*/
|
||
|
p5.prototype.clearIntervalPos = function(){
|
||
|
window.clearInterval(_intervalPosition);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Watch User's Current Position
|
||
|
*
|
||
|
* Watches the users current position
|
||
|
*
|
||
|
* @method watchPosition
|
||
|
* @param {function} a callback to handle the current position data
|
||
|
* @param {function} a callback to handle an error
|
||
|
* @param {object} an positionOptions object: enableHighAccuracy, maximumAge, timeout
|
||
|
*/
|
||
|
p5.prototype._posWatch = null;
|
||
|
p5.prototype.watchPosition = function(callback, errorCallback, options){
|
||
|
|
||
|
if (navigator.geolocation) {
|
||
|
_posWatch = navigator.geolocation.watchPosition(success, geoError, options);
|
||
|
}else{
|
||
|
geoError("geolocation not available");
|
||
|
};
|
||
|
|
||
|
function geoError(message){
|
||
|
console.log("watch Postition Error" + message);
|
||
|
if(typeof errorCallback == 'function'){ errorCallback(message.message) };
|
||
|
}
|
||
|
|
||
|
function success(position){
|
||
|
if(typeof callback == 'function'){ callback(position.coords) };
|
||
|
// console.log(_posWatch);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear the watchPosition
|
||
|
*
|
||
|
* clears the current watchPosition
|
||
|
*
|
||
|
* @method clearWatch
|
||
|
*/
|
||
|
p5.prototype.clearWatch = function(){
|
||
|
navigator.geolocation.clearWatch( _posWatch );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Calculate the Distance between two points
|
||
|
*
|
||
|
*
|
||
|
* @method watchPosition
|
||
|
* @param {float} latitude of the first point
|
||
|
* @param {float} longitude of the first point
|
||
|
* @param {float} latitude of the second point
|
||
|
* @param {float} longitude of the second point
|
||
|
* @param {string} units to use: 'km' or 'mi', 'mi' is default if left blank
|
||
|
* @return {float} the distance between the two points in the specified units, miles is default
|
||
|
*/
|
||
|
|
||
|
// http://www.movable-type.co.uk/scripts/latlong.html
|
||
|
// Used Under MIT License
|
||
|
p5.prototype.calcGeoDistance = function(lat1, lon1, lat2, lon2, units) {
|
||
|
if(units == 'km'){
|
||
|
var R = 6371; //earth radius in KM
|
||
|
}else{
|
||
|
var R = 3959; // earth radius in Miles (default)
|
||
|
}
|
||
|
var dLat = (lat2-lat1) * (Math.PI / 180);
|
||
|
var dLon = (lon2-lon1) * (Math.PI / 180);
|
||
|
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
||
|
Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) *
|
||
|
Math.sin(dLon/2) * Math.sin(dLon/2);
|
||
|
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||
|
var d = R * c;
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Calculate if a Location is inside Polygon
|
||
|
*
|
||
|
*
|
||
|
* @method watchPosition
|
||
|
* @param {float} Array of Objects with lat: and lon:
|
||
|
* @param {float} Object with lat and long of my location
|
||
|
* @return {boolean} true if geolocation is within polygon
|
||
|
*/
|
||
|
|
||
|
// http://jsfromhell.com/math/is-point-in-poly
|
||
|
// Adapted from: [http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html]
|
||
|
// Used Under MIT License
|
||
|
p5.prototype.isLocationInPolygon = function(poly, pt){
|
||
|
for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
|
||
|
((poly[i].lon <= pt.lon && pt.lon < poly[j].lon) || (poly[j].lon <= pt.lon && pt.lon < poly[i].lon))
|
||
|
&& (pt.lat < (poly[j].lat - poly[i].lat) * (pt.lon - poly[i].lon) / (poly[j].lon - poly[i].lon) + poly[i].lat)
|
||
|
&& (c = !c);
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Create a new geoFenceCircle
|
||
|
*
|
||
|
* Watches the users current position and checks to see if they are witihn a set radius of a specified point.
|
||
|
*
|
||
|
* @method watchPosition
|
||
|
* @param {float} latitude of the first point
|
||
|
* @param {float} longitude of the first point
|
||
|
* @param {float} distance from the point to trigger the insideCallback
|
||
|
* @param {function} a callback to fire when the user is inside the geoFenceCircle
|
||
|
* @param {function} a callback to fire when the user is outside the geoFenceCircle
|
||
|
* @param {string} units to use: 'km' or 'mi', 'mi' is default if left blank
|
||
|
* @param {object} an positionOptions object: enableHighAccuracy, maximumAge, timeout
|
||
|
*/
|
||
|
p5.prototype.geoFenceCircle = function(lat, lon, fence, insideCallback, outsideCallback, units, options){
|
||
|
|
||
|
this.lat = lat;
|
||
|
this.lon = lon;
|
||
|
this.fence = fence;
|
||
|
this.units = units; //this should work since calcGeoDistance defaults to miles.
|
||
|
this.distance = 0.0;
|
||
|
this.insideCallback = insideCallback;
|
||
|
this.outsideCallback = outsideCallback;
|
||
|
this.insideFence = false;
|
||
|
this.options = options;
|
||
|
this.id = '';
|
||
|
|
||
|
this.geoError = function(message){
|
||
|
console.log("geoFenceCircle Error :" + message);
|
||
|
}
|
||
|
|
||
|
this.success = function(position){
|
||
|
this.distance = calcGeoDistance(this.lat,this.lon, position.coords.latitude, position.coords.longitude, this.units);
|
||
|
|
||
|
if(this.distance <= this.fence){
|
||
|
if(typeof this.insideCallback == 'function'){ this.insideCallback(position.coords) };
|
||
|
this.insideFence = true;
|
||
|
}else{
|
||
|
if(typeof this.outsideCallback == 'function'){ this.outsideCallback(position.coords) };
|
||
|
this.insideFence = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.clear = function() {
|
||
|
if (this.id) {
|
||
|
navigator.geolocation.clearWatch(this.id);
|
||
|
this.id = '';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (navigator.geolocation) {
|
||
|
// bind the callbacks to the geoFenceCircle 'this' so we can access, this.lat, this.lon, etc..
|
||
|
this.id = navigator.geolocation.watchPosition(this.success.bind(this), this.geoError.bind(this), this.options);
|
||
|
}else{
|
||
|
geoError("geolocation not available");
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Create a new geoFencePolygon
|
||
|
*
|
||
|
* Watches the users current position and checks to see if they are witihn a set radius of a specified point.
|
||
|
*
|
||
|
* @method watchPosition
|
||
|
* @param {float} latitude of the first point
|
||
|
* @param {float} longitude of the first point
|
||
|
* @param {float} distance from the point to trigger the insideCallback
|
||
|
* @param {function} a callback to fire when the user is inside the geoFenceCircle
|
||
|
* @param {function} a callback to fire when the user is outside the geoFenceCircle
|
||
|
* @param {string} units to use: 'km' or 'mi', 'mi' is default if left blank
|
||
|
* @param {object} an positionOptions object: enableHighAccuracy, maximumAge, timeout
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*var points = [
|
||
|
{x: 34.076089, y: -118.440915},
|
||
|
{x: 34.076095, y: -118.440605},
|
||
|
{x: 34.075906, y: -118.440597},
|
||
|
{x: 34.075891, y: -118.440932},
|
||
|
];*/
|
||
|
p5.prototype.geoFencePolygon = function( ArrayOfObjectsWithLatLong, insideCallback, outsideCallback, units, options){
|
||
|
|
||
|
this.ArrayOfObjectsWithLatLong = ArrayOfObjectsWithLatLong;
|
||
|
this.units = units; //this should work since calcGeoDistance defaults to miles.
|
||
|
this.insideCallback = insideCallback;
|
||
|
this.outsideCallback = outsideCallback;
|
||
|
this.insideFence = false;
|
||
|
this.options = options;
|
||
|
this.id = '';
|
||
|
|
||
|
this.geoError = function(message){
|
||
|
console.log("geoFencePolygon Error :" + message);
|
||
|
}
|
||
|
|
||
|
this.success = function(position){
|
||
|
this.insideFence = isLocationInPolygon(this.ArrayOfObjectsWithLatLong, { lat:position.coords.latitude, lon: position.coords.longitude });
|
||
|
|
||
|
if(this.insideFence == true){
|
||
|
if(typeof this.insideCallback == 'function'){ this.insideCallback(position.coords) };
|
||
|
}else{
|
||
|
if(typeof this.outsideCallback == 'function'){ this.outsideCallback(position.coords) };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.clear = function() {
|
||
|
if (this.id) {
|
||
|
navigator.geolocation.clearWatch(this.id);
|
||
|
this.id = '';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (navigator.geolocation) {
|
||
|
// bind the callbacks to the geoFenceCircle 'this' so we can access, this.lat, this.lon, etc..
|
||
|
this.id = navigator.geolocation.watchPosition(this.success.bind(this), this.geoError.bind(this), this.options);
|
||
|
}else{
|
||
|
geoError("geolocation not available");
|
||
|
};
|
||
|
}
|