I am working on something to blacklist unwanted locations with the location service. Here is my current code:
How can I implement a blacklist feature?
if (navigator.geolocation) {
// Locate position
navigator.geolocation.getCurrentPosition(displayPosition, errorFunction);
} else {
alert('Your device location is not approved.');
}
// Success callback function
function displayPosition(pos) {
var mylat = pos.coords.latitude;
var mylong = pos.coords.longitude;
var thediv = document.getElementById('locationinfo');
alert('Your HWID is compliant of ProtoProt regulations.');
}
function errorFunction(pos) {
alert('Error: (PROTOPROT_POS_DENIED). We only use your HWID for checking compliance. Enable location to enter.');
}
Maintain a list of locations given by two points w,y.
Each w,y represent the two opposite points of a w,x,y,z square which represents the blacklisted location.
Each point has longitude and latitude coordinates, so w = [long, lat] and y = [long, lat]
With those, you can rebuild all the [long, lat] of all the w,x,y,z corners of your square, thus representing the blacklisted area.
Now, it's rather easy to know the boundaries of forbidden location: any point [long, lat] which is within the square is blacklisted.
You can store those values within a Javascript Object (a dictionary) which can be stored in a distinct ".js" file. JSON representation could look like:
blacklisted_areas = {
'area 51' : [w, y], // Replace w y with the floats of long and lat
'pink unicorn zoo' : [w, y], // same
// etc.
};
Access:
long = blacklisted_area['area 51'][0]
Related
Is there a way of converting a Latitude and Longitude value into a place name and then being able to display that name on a HTML page?
if ('geolocation' in navigator) {
let watchID = navigator.geolocation.watchPosition(position => {
let latitude = position.coords.latitude;
let longitude = position.coords.longitude;
console.log(latitude, longitude);
}, error => {
console.log(error.code);
}, {
enableHighAccuracy: true
});
console.log(watchID);
} else {
console.log("Not Supported");
}
The code can return the latitude and longitude and they can be displayed, I want to get the specific place if possible and display it on the page or record it in a table?
Basically, you need three things:
A list of places with their coordinates. That's sort of out of scope for this site.
A distance function. You can either use the cosine rule or haversine rule for that.
A nearest neighbour algorithm that's better than O(n). For that, you can e.g. partition your set from 1, google "sphere triangular tesselation" for that, and then you can optimize your nearest neighbour algorithm.
I want to calculate distance from a collection of geo coordinates. I have converted this to a GPX file and I am able to use in HERE Maps to calculate distance.
Now, I want to use this in Google Maps as per my customer requirement. Is there any option in Google Maps which accepts GPX file and return distance ? I have seen distancematrix option and believe this is in different format.
There are some parts here. The calculation based on Google Maps docs.
Notice that if you need only to calculate the distances, you don't need even google maps api. The calculation is based on the coordinates only.
Parse GPX file
GPX is basically an xml as well as html. So After you parse the content of the file using window.DOMParser().parseFromString(str, "text/xml")); you can use the DOM API (such as querySelector, querySelectorAll etc.) to retrieve all the trkpt element and extract their lat and lon values.
const coords = Array.from(xml.querySelectorAll("trkpt")).map(
element =>
new google.maps.LatLng(
Number(element.getAttribute("lat")),
Number(element.getAttribute("lon"))
)
);
I used google.maps.LatLng but you can store it in a plain object if you don't need it to interact with your map.
Calculate the distances
Iterate over the coordinates array and measure from one point to another.
function haversine_distance(coord1, coord2) {
const R = 3958.8; // Radius of the Earth in miles
const rlat1 = coord1.lat() * (Math.PI/180); // Convert degrees to radians
const rlat2 = coord2.lat() * (Math.PI/180); // Convert degrees to radians
const difflat = rlat2-rlat1; // Radian difference (latitudes)
const difflon = (coord2.lng()-coord1.lng()) * (Math.PI/180); // Radian difference (longitudes)
const d = 2 * R * Math.asin(Math.sqrt(Math.sin(difflat/2)*Math.sin(difflat/2)+Math.cos(rlat1)*Math.cos(rlat2)*Math.sin(difflon/2)*Math.sin(difflon/2)));
return d;
}
Then you can the function to build the distances array
const distances = coords.reduce((old, ne, index, original) => {
if (index > 0) {
old.push(haversine_distance(ne, original[index - 1]));
}
return old;
}, []);
https://codesandbox.io/s/elegant-turing-tvhu1?file=/index.html
I have a list with 50 items:
var mylocations = [{'id':'A', 'loc':[-21,2]},...,];
How can I in leaflet or JavaScript most efficiently make it such that if I accept an input of a specific location [<longitude>,<latitude>], a radius (e.g. 50 miles)... I can get all of the "mylocations" that fall within that circle?
Using external libraries is fine.
Leaflet's L.LatLng objects include a distanceTo method:
Returns the distance (in meters) to the given LatLng calculated using the Haversine formula.
http://leafletjs.com/reference.html#latlng-distanceto
var inRange = [], latlng_a = new L.LatLng(0, 0), latlng_b;
locations.forEach(function (location) {
latlng_b_ = new L.LatLng(location.pos[0], location.pos[1]);
if (latlng_a.distanceTo(latlng_b) < 80.4672) {
inRange.push(location);
}
});
I have locations stored in mongodb that look like this in mongoose schema:
location: {
type: [Number],
index: '2d'
}
And on web client I'm using google maps api with custom radius resizer:
On each drag I'm making request with radius value that is calculated on client. Radius is the distance between pink arrow marker and center coordinates:
function metersToMiles (meters) {
return meters * 0.000621371192;
}
google.maps.event.addListener(this.sizer, 'dragend', () => {
const radius = this.circle.getRadius();
const radiusValue = Math.round(metersToMiles(radius) * 10) / 10; // convert to tenths (this is shown on UI as well)
this.props.onRadiusChange(radiusValue); // it's a react component
});
In mongodb request I'm using $nearSphere with radius in $maxDistance:
function milesToRadian(miles){
const earthRadiusInMiles = 3963.2;
return parseFloat(miles) / earthRadiusInMiles;
}
const { radius, lat, lon } = req.query;
const coords = (lat && lon) ? [lat, lon] : ukCoordinates;
const radians = milesToRadian(radius);
console.log('%s, %s, %s', radius, coords, radians);
// what I receive: 1.6, 0.00040371417036737993, [ 51.507351, -0.127758 ]
// ...
{
$nearSphere: coords,
$maxDistance: radians
}
However if you take a look on the gif image you'll see that there's some inaccuracy in results. For now I'm stucked with it, could you suggest what is the problem?
So the problem was really funny but still tricky. I've found out that in MongoDB you need to store coordinate pairs as [longitude, latitude] and not vice versa:
location: {
type: [Number], // longitude, latitude
index: '2d'
}
But in Google Maps SDK the order is different:
new google.maps.LatLng(lat, lng);
So to fix my problem I've needed to store coordinates in right order in MongoDB.
I'm trying to distort a d3.geo.path() map with the fisheye.js plugin (https://github.com/d3/d3-plugins/tree/master/fisheye).
To distort an object the plugin needs x & y attributes.
In the d3.js wiki it says:
A projection function takes a two-element array of numbers representing the coordinates of a location, [longitude, latitude], and returns a similar two-element array of numbers representing the projected pixel position [x, y]. For example, a rudimentary spherical Mercator projection:
https://github.com/mbostock/d3/wiki/Geo-Paths
So the distortion should be possible, I just can't wrap my head around it.
I'm using the world-50m.json for my projection. Once loaded there is an the arcs array. I think those are the coordinates I need to manipulate. But this is guesswork...
Thanks,
Kim
I found your post looking for the answer, and it doesn't appear to be out there on the internets. But, like you say, it's possible!
Following the documentation from the fisheye.js (https://github.com/d3/d3-plugins/tree/master/fisheye), in the mousemove callback you need to use fisheye on the coordinates.
Since fisheye uses the .x and .y attributes, I modified the fisheye code to just use the two pair [x,y] to avoid making that intermediate data structure every time in the callback.
Then you can do it like this:
canvas.on("mousemove", function() {
// console.log("mouse:");
// console.log(d3.mouse(this));
var here = d3.mouse(this);
// console.log(here); // [1030, 125]
// console.log(projection.invert(here)); // [-72.4713375653601, 45.14035261565636]
var inverted = projection.invert([here[0],here[1]]); // [-72.4713375653601, 45.14035261565636]
// console.log(inverted); // [-72.4713375653601, 45.14035261565636]
// burlington is lat 44, lon -73
fisheye.focus(inverted);
// of course, the path function takes [longitude, latitude], so -72, 44 for burlington
// https://github.com/mbostock/d3/wiki/Geo-Paths
// (so that's what it gives back)
states.attr("d",null)
.attr("d", function(d) {
// console.log("original:");
// console.log(d.geometry);
if (d.geometry.type === "Polygon") {
var b = d.geometry.coordinates.map(function(d) { return d.map(function(f) { return fisheye(f);}); });
}
else {
var b = d.geometry.coordinates.map(function(d) { return d.map(function(f) { return f.map(function(g) { return fisheye(g); }); }); });
}
// console.log(b);
var c = {type: d.geometry.type, coordinates: b};
// console.log("new:");
// console.log(c);
return path(c);
});
You can view a live version here: http://panometer.org/instruments/teletherms/?window=25&var=maxT&year=1914&city=BURLINGTON%20WSO%20AP,%20VT