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

7 months 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");
};
}