I want to find my friends by taking their location from their mobile phone who are near to me from my current location.
For example in my code below I have var cities, If I put 3,4 numbers of my friends so I can do this? Or can I do this making some other changes? Is it possible?
// Get User's Coordinate from their Browser
window.onload = function () {
// HTML5/W3C Geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(UserLocation);
}
// Default to Washington, DC
else
NearestCity(38.8951, -77.0367);
}
// Callback function for asynchronous call to HTML5 geolocation
function UserLocation(position) {
NearestCity(position.coords.latitude, position.coords.longitude);
}
// Convert Degress to Radians
function Deg2Rad(deg) {
return deg * Math.PI / 180;
}
function PythagorasEquirectangular(lat1, lon1, lat2, lon2) {
lat1 = Deg2Rad(lat1);
lat2 = Deg2Rad(lat2);
lon1 = Deg2Rad(lon1);
lon2 = Deg2Rad(lon2);
var R = 6371; // km
var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
var y = (lat2 - lat1);
var d = Math.sqrt(x * x + y * y) * R;
return d;
}
var lat = 20; // user's latitude
var lon = 40; // user's longitude
var cities = [
["city1", 10, 50, "blah"],
["city2", 40, 60, "blah"],
["city3", 25, 10, "blah"],
["city4", 5, 80, "blah"]
];
function NearestCity(latitude, longitude) {
var mindif = 99999;
var closest;
for (index = 0; index < cities.length; ++index) {
var dif = PythagorasEquirectangular(latitude, longitude, cities[index]
[1], cities[index][2]);
if (dif < mindif) {
closest = index;
mindif = dif;
}
}
// echo the nearest city
alert(cities[closest]);
}
I suggest using GeoFire for that purpose it is from firebase and has Geographical based queries and can do what you want in an easy way
Related
I have a function to convert latitude and longitude to localCordinateSystem
const EARTH_RADIUS_KM = 6371.0;
const distanceInMeters = (lat1, lon1, lat2, lon2) => {
const lonDiff = toRadians(lon2 - lon1);
const latDiff = toRadians(lat2 - lat1);
const a = Math.pow(Math.sin(latDiff / 2), 2) + Math.cos(toRadians(lat1)) *
Math.cos(toRadians(lat2)) * Math.pow(Math.sin(lonDiff / 2), 2);
const angle = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return angle * EARTH_RADIUS_KM * 1000.0;
};
const localCoordinateSystem = (lat, lon, originLat, originLon, radius) => {
let latDist = distanceInMeters(originLat, originLon, lat, originLon);
let lonDist = distanceInMeters(originLat, originLon, originLat, lon);
if (lat < originLat) latDist *= -1;
if (lon < originLon) lonDist *= -1;
return {
x: parseFloat(latDist) + parseFloat(radius),
y: parseFloat(lonDist) + parseFloat(radius),
};
};
If you see the function localCoordinateSystem takes lat, lon, originLat, originLon and radius and returns x and y.
But now I want a function that takes x, y, originLat, originLon and radius and returns lat and lon.
I`ve got a map with a polyline. The server will responds me with a LatLng point on a map. I need to check if the point from the server situated on a polyline edge. If not, i need to find the nearest point on the polyline and place a marker on the nearest point on the polyline. For example, if the server responds me with a point A, i need to place a marker to a point B.
I find a good library http://wtp2.appspot.com/cSnapToRouteDemo.html, but this library is for Google API ver. 2, and i'm using Google API ver. 3. Is there any alternative for Google API ver. 3 ? Thank's.
Found an easier solution.Using turf.js.Just use your polyline coordinates to create turf line and marker position for creating turf point.
then;
var line = turf.lineString(Your polyline coordinates in GeoJson array);
var pt = turf.point([Marker_Lon, Marker_Lat]);
var snapped = turf.pointOnLine(line, pt);
var pstnOnLine = { lat: snapped.geometry.coordinates[1], lng: snapped.geometry.coordinates[0] };
var distToLine = snapped.properties.dist
This way you can calculate the distance and coordinates on your polyline easily.
You can find out more from Turf website.
The Google Maps Javascript API has a Geometry library.
The Geometry library has a isLocationOnEdge function. See the documentation.
To determine whether a point falls on or near a polyline, or on or near the edge of a polygon, pass the point, the polyline/polygon, and optionally a tolerance value in degrees to google.maps.geometry.poly.isLocationOnEdge(). The function returns true if the distance between the point and the closest point on the line or edge falls within the specified tolerance. The default tolerance value is 10-9 degrees.
You must include the library this way:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">
</script>
And if you need more than one library, for example:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry,places">
</script>
Full documentation is here.
If you need to find the point on the Polyline, you can use this ported to v3 version of the library you mentioned in your question:
var mapRoute;
var rtPoints;
var centerMAP = new google.maps.LatLng(-7.402438, 110.446957);
function gLatLngFromEN(e, n) {
var ogbLL = NEtoLL(e, n);
var pc = OGBToWGS84(ogbLL.lat, ogbLL.lon, 0);
return new google.maps.LatLng(pc.lat, pc.lon);
}
function routeMap() {
mapRoute = new google.maps.Map(document.getElementById('mapRoute'), {
center: centerMAP,
zoom: 14,
mapTypeId: google.maps.MapTypeId.SATELLITE
});
mapRoute.setCenter(gLatLngFromEN(469000, 169000), 13);
var rtPoints = new Array();
rtPoints.push(gLatLngFromEN(468000, 168000));
rtPoints.push(gLatLngFromEN(468000, 170000));
rtPoints.push(gLatLngFromEN(470000, 170000));
rtPoints.push(gLatLngFromEN(470000, 168000));
var rtPoly = new google.maps.Polyline({
path: rtPoints,
strokeColor: "#0000FF",
strokeWeight: 3,
map: mapRoute
});
var container = document.createElement("div");
container.style.fontFamily = 'Arial';
container.style.fontSize = 'XX-Small';
var ptr = document.createElement("INPUT");
ptr.style.width = "100px";
ptr.type = "Text";
ptr.readOnly = true;
ptr.id = "distPtr";
container.appendChild(ptr);
document.getElementById("control").appendChild(container);
google.maps.event.addListener(mapRoute, 'mousemove', function (point) {
document.getElementById('distPtr').value = Math.round(bdccGeoDistanceToPolyMtrs(rtPoly, point.latLng));
});
}
google.maps.event.addDomListener(window, 'load', routeMap);
// Code to find the distance in metres between a lat/lng point and a polyline of lat/lng points
// All in WGS84. Free for any use.
//
// Bill Chadwick 2007
// updated to Google Maps API v3, Lawrence Ross 2014
// Construct a bdccGeo from its latitude and longitude in degrees
function bdccGeo(lat, lon)
{
var theta = (lon * Math.PI / 180.0);
var rlat = bdccGeoGeocentricLatitude(lat * Math.PI / 180.0);
var c = Math.cos(rlat);
this.x = c * Math.cos(theta);
this.y = c * Math.sin(theta);
this.z = Math.sin(rlat);
}
bdccGeo.prototype = new bdccGeo();
// internal helper functions =========================================
// Convert from geographic to geocentric latitude (radians).
function bdccGeoGeocentricLatitude(geographicLatitude)
{
var flattening = 1.0 / 298.257223563;//WGS84
var f = (1.0 - flattening) * (1.0 - flattening);
return Math.atan((Math.tan(geographicLatitude) * f));
}
// Convert from geocentric to geographic latitude (radians)
function bdccGeoGeographicLatitude (geocentricLatitude)
{
var flattening = 1.0 / 298.257223563;//WGS84
var f = (1.0 - flattening) * (1.0 - flattening);
return Math.atan(Math.tan(geocentricLatitude) / f);
}
// Returns the two antipodal points of intersection of two great
// circles defined by the arcs geo1 to geo2 and
// geo3 to geo4. Returns a point as a Geo, use .antipode to get the other point
function bdccGeoGetIntersection( geo1, geo2, geo3, geo4)
{
var geoCross1 = geo1.crossNormalize(geo2);
var geoCross2 = geo3.crossNormalize(geo4);
return geoCross1.crossNormalize(geoCross2);
}
//from Radians to Meters
function bdccGeoRadiansToMeters(rad)
{
return rad * 6378137.0; // WGS84 Equatorial Radius in Meters
}
//from Meters to Radians
function bdccGeoMetersToRadians(m)
{
return m / 6378137.0; // WGS84 Equatorial Radius in Meters
}
// properties =================================================
bdccGeo.prototype.getLatitudeRadians = function()
{
return (bdccGeoGeographicLatitude(Math.atan2(this.z,
Math.sqrt((this.x * this.x) + (this.y * this.y)))));
}
bdccGeo.prototype.getLongitudeRadians = function()
{
return (Math.atan2(this.y, this.x));
}
bdccGeo.prototype.getLatitude = function()
{
return this.getLatitudeRadians() * 180.0 / Math.PI;
}
bdccGeo.prototype.getLongitude = function()
{
return this.getLongitudeRadians() * 180.0 / Math.PI ;
}
// Methods =================================================
//Maths
bdccGeo.prototype.dot = function( b)
{
return ((this.x * b.x) + (this.y * b.y) + (this.z * b.z));
}
//More Maths
bdccGeo.prototype.crossLength = function( b)
{
var x = (this.y * b.z) - (this.z * b.y);
var y = (this.z * b.x) - (this.x * b.z);
var z = (this.x * b.y) - (this.y * b.x);
return Math.sqrt((x * x) + (y * y) + (z * z));
}
//More Maths
bdccGeo.prototype.scale = function( s)
{
var r = new bdccGeo(0,0);
r.x = this.x * s;
r.y = this.y * s;
r.z = this.z * s;
return r;
}
// More Maths
bdccGeo.prototype.crossNormalize = function( b)
{
var x = (this.y * b.z) - (this.z * b.y);
var y = (this.z * b.x) - (this.x * b.z);
var z = (this.x * b.y) - (this.y * b.x);
var L = Math.sqrt((x * x) + (y * y) + (z * z));
var r = new bdccGeo(0,0);
r.x = x / L;
r.y = y / L;
r.z = z / L;
return r;
}
// point on opposite side of the world to this point
bdccGeo.prototype.antipode = function()
{
return this.scale(-1.0);
}
//distance in radians from this point to point v2
bdccGeo.prototype.distance = function( v2)
{
return Math.atan2(v2.crossLength(this), v2.dot(this));
}
//returns in meters the minimum of the perpendicular distance of this point from the line segment geo1-geo2
//and the distance from this point to the line segment ends in geo1 and geo2
bdccGeo.prototype.distanceToLineSegMtrs = function(geo1, geo2)
{
//point on unit sphere above origin and normal to plane of geo1,geo2
//could be either side of the plane
var p2 = geo1.crossNormalize(geo2);
// intersection of GC normal to geo1/geo2 passing through p with GC geo1/geo2
var ip = bdccGeoGetIntersection(geo1,geo2,this,p2);
//need to check that ip or its antipode is between p1 and p2
var d = geo1.distance(geo2);
var d1p = geo1.distance(ip);
var d2p = geo2.distance(ip);
//window.status = d + ", " + d1p + ", " + d2p;
if ((d >= d1p) && (d >= d2p))
return bdccGeoRadiansToMeters(this.distance(ip));
else
{
ip = ip.antipode();
d1p = geo1.distance(ip);
d2p = geo2.distance(ip);
}
if ((d >= d1p) && (d >= d2p))
return bdccGeoRadiansToMeters(this.distance(ip));
else
return bdccGeoRadiansToMeters(Math.min(geo1.distance(this),geo2.distance(this)));
}
// distance in meters from GLatLng point to GPolyline or GPolygon poly
function bdccGeoDistanceToPolyMtrs(poly, point)
{
var d = 999999999;
var i;
var p = new bdccGeo(point.lat(),point.lng());
for(i=0; i<(poly.getPath().getLength()-1); i++)
{
var p1 = poly.getPath().getAt(i);
var l1 = new bdccGeo(p1.lat(),p1.lng());
var p2 = poly.getPath().getAt(i+1);
var l2 = new bdccGeo(p2.lat(),p2.lng());
var dp = p.distanceToLineSegMtrs(l1,l2);
if(dp < d)
d = dp;
}
return d;
}
// get a new GLatLng distanceMeters away on the compass bearing azimuthDegrees
// from the GLatLng point - accurate to better than 200m in 140km (20m in 14km) in the UK
function bdccGeoPointAtRangeAndBearing (point, distanceMeters, azimuthDegrees)
{
var latr = point.lat() * Math.PI / 180.0;
var lonr = point.lng() * Math.PI / 180.0;
var coslat = Math.cos(latr);
var sinlat = Math.sin(latr);
var az = azimuthDegrees* Math.PI / 180.0;
var cosaz = Math.cos(az);
var sinaz = Math.sin(az);
var dr = distanceMeters / 6378137.0; // distance in radians using WGS84 Equatorial Radius
var sind = Math.sin(dr);
var cosd = Math.cos(dr);
return new google.maps.LatLng(Math.asin((sinlat * cosd) + (coslat * sind * cosaz)) * 180.0 / Math.PI,
(Math.atan2((sind * sinaz), (coslat * cosd) - (sinlat * sind * cosaz)) + lonr) * 180.0 / Math.PI);
}
Credits to Bill Chadwick 2007 and Lawrence Ross 2014 for the v3 version. And #geocodezip for finding it.
JSFiddle demo
I need to limit the radius of the great circle problem. The circle will extend until it hits another item.
I need it to limit the range of the circle to 5 miles
Here is my code
function find_closest_ticket(ticket, lat, lng) {
// var lat = map.position.coords.latitude;
// var lon = map.position.coords.longitude;
// lat = 24.709254;
// lng = -81.381927;
var R = 6371; // radius of earth in km
var distances = [];
var closest = -1;
for (i = 0; i < ticket.length; i++) {
var mlat = ticket[i].soLAT;
var mlng = ticket[i].soLNG;
var dLat = rad(mlat - lat);
var dLong = rad(mlng - lng);
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
return closest;
}
First, it is surprising you use a function that returns a radius in km, and then want to limit it to 5 miles. You should make up your mind: either write the function to return miles and add the limit in miles, or leave the function as-is and limit it by km (8 km is roughly 5 miles).
If you want to use miles, then change this line:
var R = 6371; // radius of earth in km
to:
var R = 3959; // radius of earth in miles
and replace:
return closest;
by:
return Math.min(5, closest);
Alternatively, if you want to stick to km, then only replace:
return closest;
by:
return Math.min(8, closest);
I want to show specific information depending on where i am.
I have five cities with different information, and i want to show that city(information) that i'm closest to.
How to i do that the simplest way, using javascript.
Ex.
If i store the cities lat, long in an array
var cities = [
['new york', '111111', '222222', 'blablabla']
['boston', '111111', '222222', 'blablabla']
['seattle', '111111', '222222', 'blablabla']
['london', '111111', '222222', 'blablabla']
]
And with my current location(lat, long) i want the city that i'm closet to.
Here is a basic code example using HTML5 geolocation to get the user's position. It then calls NearestCity() and calculates the distance (km) from the location to each city. I passed on using the Haversine formulae and instead used the simpler Pythagoras formulae and an equirectangular projection to adjust for the curvature in longitude lines.
// Get User's Coordinate from their Browser
window.onload = function() {
// HTML5/W3C Geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(UserLocation);
}
// Default to Washington, DC
else
NearestCity(38.8951, -77.0367);
}
// Callback function for asynchronous call to HTML5 geolocation
function UserLocation(position) {
NearestCity(position.coords.latitude, position.coords.longitude);
}
// Convert Degress to Radians
function Deg2Rad(deg) {
return deg * Math.PI / 180;
}
function PythagorasEquirectangular(lat1, lon1, lat2, lon2) {
lat1 = Deg2Rad(lat1);
lat2 = Deg2Rad(lat2);
lon1 = Deg2Rad(lon1);
lon2 = Deg2Rad(lon2);
var R = 6371; // km
var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
var y = (lat2 - lat1);
var d = Math.sqrt(x * x + y * y) * R;
return d;
}
var lat = 20; // user's latitude
var lon = 40; // user's longitude
var cities = [
["city1", 10, 50, "blah"],
["city2", 40, 60, "blah"],
["city3", 25, 10, "blah"],
["city4", 5, 80, "blah"]
];
function NearestCity(latitude, longitude) {
var minDif = 99999;
var closest;
for (index = 0; index < cities.length; ++index) {
var dif = PythagorasEquirectangular(latitude, longitude, cities[index][1], cities[index][2]);
if (dif < minDif) {
closest = index;
minDif = dif;
}
}
// echo the nearest city
alert(cities[closest]);
}
With HTML5, you can pull the location of the user and then compares this example using a Haversine function (function below taken from here):
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}
You can calculate the distance by latitude with your location and the cities locations. And find the shortest and draw. To calculate you can read more in http://www.movable-type.co.uk/scripts/latlong.html
When i click on map, which will be best way to find nearest marker or markers? is there some functions in api that will help me to do that?
it's google map api v3.
First you have to add the eventlistener
google.maps.event.addListener(map, 'click', find_closest_marker);
Then create a function that loops through the array of markers and uses the haversine formula to calculate the distance of each marker from the click.
function rad(x) {return x*Math.PI/180;}
function find_closest_marker( event ) {
var lat = event.latLng.lat();
var lng = event.latLng.lng();
var R = 6371; // radius of earth in km
var distances = [];
var closest = -1;
for( i=0;i<map.markers.length; i++ ) {
var mlat = map.markers[i].position.lat();
var mlng = map.markers[i].position.lng();
var dLat = rad(mlat - lat);
var dLong = rad(mlng - lng);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong/2) * Math.sin(dLong/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
distances[i] = d;
if ( closest == -1 || d < distances[closest] ) {
closest = i;
}
}
alert(map.markers[closest].title);
}
This keeps track of the closest markers and alerts its title.
I have my markers as an array on my map object
You can use the computeDistanceBetween() method in the google.maps.geometry.spherical namespace.
I'd like to expand on Leor's suggestion and provide a working solution:
I'm using markers in a markers array e.g. var markers = [];.
Then let's have our position as something like var location = new google.maps.LatLng(51.99, -0.74);
Then we simply reduce our markers against the location we have like so:
markers.reduce(function (prev, curr) {
var cpos = google.maps.geometry.spherical.computeDistanceBetween(location.position, curr.position);
var ppos = google.maps.geometry.spherical.computeDistanceBetween(location.position, prev.position);
return cpos < ppos ? curr : prev;
}).position
What pops out is your closest marker LatLng object.
The formula above didn't work for me, but I used this without any issue. Pass your current location to the function, and loop through an array of markers to find the closest:
function find_closest_marker( lat1, lon1 ) {
var pi = Math.PI;
var R = 6371; //equatorial radius
var distances = [];
var closest = -1;
for( i=0;i<markers.length; i++ ) {
var lat2 = markers[i].position.lat();
var lon2 = markers[i].position.lng();
var chLat = lat2-lat1;
var chLon = lon2-lon1;
var dLat = chLat*(pi/180);
var dLon = chLon*(pi/180);
var rLat1 = lat1*(pi/180);
var rLat2 = lat2*(pi/180);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(rLat1) * Math.cos(rLat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
distances[i] = d;
if ( closest == -1 || d < distances[closest] ) {
closest = i;
}
}
// (debug) The closest marker is:
console.log(markers[closest]);
}
Are you aware of Mysql Spatial extensions?
You could use something like MBRContains(g1,g2).
Use computeDistanceBetween() Google map API method to calculate near marker between your location and markers list on google map.
Steps:-
Create marker on google map.
function addMarker(location) {
var marker = new google.maps.Marker({
title: 'User added marker',
icon: {
path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
scale: 5
},
position: location,
map: map
});
}
On Mouse click create event for getting lat, long of your location and pass that to find_closest_marker().
function find_closest_marker(event) {
var distances = [];
var closest = -1;
for (i = 0; i < markers.length; i++) {
var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].position, event.latLng);
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
alert('Closest marker is: ' + markers[closest].getTitle());
}
visit this link follow the steps. You will able to get nearer marker to your location.
Here is another function that works great for me, returns distance in kilometers:
function distance(lat1, lng1, lat2, lng2) {
var radlat1 = Math.PI * lat1 / 180;
var radlat2 = Math.PI * lat2 / 180;
var radlon1 = Math.PI * lng1 / 180;
var radlon2 = Math.PI * lng2 / 180;
var theta = lng1 - lng2;
var radtheta = Math.PI * theta / 180;
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
dist = Math.acos(dist);
dist = dist * 180 / Math.PI;
dist = dist * 60 * 1.1515;
//Get in in kilometers
dist = dist * 1.609344;
return dist;
}