我正在尝试制作一个网站,询问用户的位置,然后使用 GeoLocation 找到距其位置最近的位置(100m 半径)并以 HTML 形式显示结果。
我已经尝试过了。
$.getJSON("places.json", function (data) {
for (var i = 0; i < data.length; i++) {
if ((data[i].lat - poslat) > 0.00200 || (data[i].lng - poslng) > 0.00200) {
return data[i];
}
html += '<p>' + data[i].location + ' - ' + data[i].code + '</p>';
$('#nearbystops').append(html);
}
});
places.json
[
{
"code": "0001",
"lat": "1.28210155945393",
"lng": "103.81722480263163",
"location": "Stop 1"
},
{
"code": "0003",
"lat": "1.2777380589964",
"lng": "103.83749709165197",
"location": "Stop 2"
},
{
"code": "0002",
"lat": "1.27832046633393",
"lng": "103.83762574759974",
"location": "Stop 3"
}
]
提前谢谢您! :)
要计算两个坐标之间的距离,不能只将值相减。 这很好,但它为您提供了正方形内的坐标。 这可能是合适的,但大多数人确实倾向于按半径搜索位置。 这个函数可以做到这一点...
function distance(lat1, lon1, lat2, lon2, unit) {
var radlat1 = Math.PI * lat1/180
var radlat2 = Math.PI * lat2/180
var theta = lon1-lon2
var radtheta = Math.PI * theta/180
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;
}
dist = Math.acos(dist)
dist = dist * 180/Math.PI
dist = dist * 60 * 1.1515
if (unit=="K") { dist = dist * 1.609344 }
if (unit=="N") { dist = dist * 0.8684 }
return dist
}
这是我从这里复制的一段常见代码...
https://www.geodatasource.com/developers/javascript
这就是,在您的示例中使用的...
function distance(lat1, lon1, lat2, lon2, unit) {
var radlat1 = Math.PI * lat1/180
var radlat2 = Math.PI * lat2/180
var theta = lon1-lon2
var radtheta = Math.PI * theta/180
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;
}
dist = Math.acos(dist)
dist = dist * 180/Math.PI
dist = dist * 60 * 1.1515
if (unit=="K") { dist = dist * 1.609344 }
if (unit=="N") { dist = dist * 0.8684 }
return dist
}
var data = [{
"code": "0001",
"lat": "1.28210155945393",
"lng": "103.81722480263163",
"location": "Stop 1"
}, {
"code": "0003",
"lat": "1.2777380589964",
"lng": "103.83749709165197",
"location": "Stop 2"
}, {
"code": "0002",
"lat": "1.27832046633393",
"lng": "103.83762574759974",
"location": "Stop 3"
}];
var html = "";
var poslat = 1.28210155945393;
var poslng = 103.81722480263163;
for (var i = 0; i < data.length; i++) {
// if this location is within 0.1KM of the user, add it to the list
if (distance(poslat, poslng, data[i].lat, data[i].lng, "K") <= 0.1) {
html += '<p>' + data[i].location + ' - ' + data[i].code + '</p>';
}
}
$('#nearbystops').append(html);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="nearbystops"></div>
使用 HTML5 地理定位获取当前用户的位置,并找到 100 米内最近的位置。
包含并使用下面的谷歌地图库
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry"> </script>
片段
//calculates distance between two points in km's
function calcDistance(p1, p2) {
return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
}
function getPosition(position) {
var userPosition = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
$.getJSON("places.json", function(data) {
for (var i = 0; i < data.length; i++) {
var p1 = new google.maps.LatLng(userPosition.lat, userPosition.lng);
var p2 = new google.maps.LatLng(data[i].lat, data[i].lng);
var distance = calcDistance(p1, p2) * 1000;
if ((distance * 1000) <= 100) {
html += '<p>' + data[i].location + ' - ' + data[i].code + '</p>';
$('#nearbystops').append(html);
}
}
})
}
// get user's current latitude & longitude
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(getPosition);
} else {
alert("Geolocation is not supported by this browser.");
}
}
getLocation();
为了计算两点之间的距离(纬度,经度),在打字稿中实现了半正弦公式的函数。
//There are 6200 points in the JSON file
import data from './json/test.json';
let radians = function (degree: number) {
// degrees to radians
let rad: number = degree * Math.PI / 180;
return rad;
}
const haversine = (lat1: number, lon1: number, lat2: number, lon2: number) => {
let dlat, dlon, a, c, R: number;
R = 6372.8; // km
dlat = radians(lat2 - lat1);
dlon = radians(lon2 - lon1);
lat1 = radians(lat1);
lat2 = radians(lat2);
a = Math.sin(dlat / 2) * Math.sin(dlat / 2) + Math.sin(dlon / 2) * Math.sin(dlon / 2) * Math.cos(lat1) * Math.cos(lat2)
c = 2 * Math.asin(Math.sqrt(a));
return R * c;
}
let test = function () {
const keys = Object.keys(data);
let count: number = keys.length;
for (var _i = 0; _i < count; _i++) {
var _dummy: number = haversine(
36.12, -86.67, data[_i].position.lat, data[_i].position.lng);
}
}
您可以使用一些算法:
1。文森特公式 Vincenty 公式是一种计算椭球表面两点之间距离的迭代方法。它比半正矢公式更准确,特别是对于较长的距离。它解释了地球的扁球体形状,提供了更好的精度。
2。等距矩形近似的大圆距离 对于快速、不太精确的计算,可以使用等距矩形近似。它速度更快,但准确性较差,尤其是随着距离的增加。
3.测地线计算 Python 中的 geopy 等库提供了更复杂的测地线计算,可以更精确地处理地球的曲率。他们使用各种模型(例如 WGS84 椭球体)来提高准确性。
4。余弦球面定律 余弦球面定律是另一种类似于半正矢公式的方法,但在某些情况下可能提供略有不同的精度特性。
每种方法何时使用:
// Haversine algorithm:
interface City {
city: string;
lat: number;
lng: number;
}
const cityCoordinates: City[] = [
{ city: 'Sydney', lat: -33.8688, lng: 151.2093 },
{ city: 'Melbourne', lat: -37.8136, lng: 144.9631 },
{ city: 'Wollongong', lat: -34.4278, lng: 150.8931 },
{ city: 'Canberra', lat: -35.2802, lng: 149.1310 },
{ city: 'Brisbane', lat: -27.4698, lng: 153.0251 },
{ city: 'Perth', lat: -31.9505, lng: 115.8605 }
];
const userLocation: { city: string; lat: number; lng: number } = {
city: 'Anna Bay',
lat: -32.7790,
lng: 152.0858
};
// Function to calculate the distance between two coordinates using Haversine formula
const calculateDistance = (lat1: number, lng1: number, lat2: number, lng2: number): number => {
const toRadians = (degree: number) => degree * (Math.PI / 180);
const R = 6371; // Radius of the Earth in km
const dLat = toRadians(lat2 - lat1);
const dLng = toRadians(lng2 - lng1);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLng / 2) * Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; // Distance in km
};
// Find the closest city to the user's location
const findClosestCity = (userLat: number, userLng: number, cities: City[]): City => {
let closest: City & { distance: number } = { city: '', lat: 0, lng: 0, distance: Infinity };
cities.forEach(city => {
const distance = calculateDistance(userLat, userLng, city.lat, city.lng);
console.log(`Distance from ${userLocation.city} to ${city.city}: ${distance.toFixed(2)} km`); // Debugging line
if (distance < closest.distance) {
closest = { ...city, distance };
}
});
return closest;
};
const closestCity = findClosestCity(userLocation.lat, userLocation.lng, cityCoordinates);
console.log(closestCity)
// Vincenty’s algorithm
interface City {
city: string;
lat: number;
lng: number;
}
const cityCoordinates: City[] = [
{ city: 'Sydney', lat: -33.8688, lng: 151.2093 },
{ city: 'Melbourne', lat: -37.8136, lng: 144.9631 },
{ city: 'Wollongong', lat: -34.4278, lng: 150.8931 },
{ city: 'Canberra', lat: -35.2802, lng: 149.1310 },
{ city: 'Brisbane', lat: -27.4698, lng: 153.0251 },
{ city: 'Perth', lat: -31.9505, lng: 115.8605 }
];
const userLocation: { city: string; lat: number; lng: number } = {
city: 'Anna Bay',
lat: -32.7790,
lng: 152.0858
};
// Vincenty’s formula for distance calculation
const vincentyDistance = (lat1: number, lng1: number, lat2: number, lng2: number): number => {
const a = 6378137; // Radius of the Earth in meters
const f = 1 / 298.257223563; // Flattening of the ellipsoid
const b = (1 - f) * a; // Semi-minor axis
const φ1 = lat1 * Math.PI / 180;
const λ1 = lng1 * Math.PI / 180;
const φ2 = lat2 * Math.PI / 180;
const λ2 = lng2 * Math.PI / 180;
const L = λ2 - λ1;
const U1 = Math.atan((1 - f) * Math.tan(φ1));
const U2 = Math.atan((1 - f) * Math.tan(φ2));
const sinU1 = Math.sin(U1);
const cosU1 = Math.cos(U1);
const sinU2 = Math.sin(U2);
const cosU2 = Math.cos(U2);
let λ = L;
let λP: number;
let iterLimit = 100;
let cos2σM: number;
let sinσ: number;
let cosσ: number;
let σ: number;
let sinα: number;
let cos2α: number;
let C: number;
do {
sinσ = Math.sqrt(
(cosU2 * Math.sin(λ)) ** 2 +
(cosU1 * sinU2 - sinU1 * cosU2 * Math.cos(λ)) ** 2
);
cosσ = sinU1 * sinU2 + cosU1 * cosU2 * Math.cos(λ);
σ = Math.atan2(sinσ, cosσ);
sinα = (cosU1 * cosU2 * Math.sin(λ)) / sinσ;
cos2α = 1 - sinα ** 2;
cos2σM = cosσ - 2 * sinU1 * sinU2 / cos2α;
C = f / 16 * cos2α * (4 + f * (4 - 3 * cos2α));
λP = λ;
λ = L + (1 - C) * f * sinα * (
σ + C * sinσ * (
cos2σM + C * cosσ * (-1 + 2 * cos2σM ** 2)
)
);
} while (Math.abs(λ - λP) > 1e-12 && --iterLimit > 0);
const u2 = cos2α * ((a ** 2 - b ** 2) / (b ** 2));
const A = 1 + (u2 / 16384) * (4096 + u2 * (-768 + u2 * (320 - 175 * u2)));
const B = (u2 / 1024) * (256 + u2 * (-128 + u2 * (74 - 47 * u2)));
const Δσ = B * sinσ * (
cos2σM + (B / 4) * (
cosσ * (-1 + 2 * cos2σM ** 2) -
(B / 6) * cos2σM * (-3 + 4 * sinσ ** 2) * (-3 + 4 * cos2σM ** 2)
)
);
const s = b * A * (σ - Δσ);
return s / 1000; // Convert to kilometers
};
// Find the closest city to the user's location
const findClosestCity = (userLat: number, userLng: number, cities: City[]): City & { distance: number } => {
let closest: City & { distance: number } = { city: '', lat: 0, lng: 0, distance: Infinity };
cities.forEach(city => {
const distance = vincentyDistance(userLat, userLng, city.lat, city.lng);
console.log(`Distance from ${userLocation.city} to ${city.city}: ${distance.toFixed(2)} km`); // Debugging line
if (!isNaN(distance) && distance < closest.distance) {
closest = { ...city, distance };
}
});
return closest;
};
const closestCity = findClosestCity(userLocation.lat, userLocation.lng, cityCoordinates);
console.log('Closest City:', closestCity);
// Equirectangular Approximation algorithm
interface City {
city: string;
lat: number;
lng: number;
}
const cityCoordinates: City[] = [
{ city: 'Sydney', lat: -33.8688, lng: 151.2093 },
{ city: 'Melbourne', lat: -37.8136, lng: 144.9631 },
{ city: 'Wollongong', lat: -34.4278, lng: 150.8931 },
{ city: 'Canberra', lat: -35.2802, lng: 149.1310 },
{ city: 'Brisbane', lat: -27.4698, lng: 153.0251 },
{ city: 'Perth', lat: -31.9505, lng: 115.8605 }
];
const userLocation: { city: string; lat: number; lng: number } = {
city: 'Anna Bay',
lat: -32.7790,
lng: 152.0858
};
// Equirectangular approximation for distance calculation
const equirectangularDistance = (lat1: number, lng1: number, lat2: number, lng2: number): number => {
const R = 6371; // Radius of the Earth in km
const x = (lng2 - lng1) * Math.cos((lat1 + lat2) / 2 * Math.PI / 180);
const y = lat2 - lat1;
return Math.sqrt(x * x + y * y) * R;
};
// Find the closest city to the user's location
const findClosestCity = (userLat: number, userLng: number, cities: City[]): City & { distance: number } => {
let closest: City & { distance: number } = { city: '', lat: 0, lng: 0, distance: Infinity };
cities.forEach(city => {
const distance = equirectangularDistance(userLat, userLng, city.lat, city.lng);
console.log(`Distance from ${userLocation.city} to ${city.city}: ${distance.toFixed(2)} km`); // Debugging line
if (distance < closest.distance) {
closest = { ...city, distance };
}
});
return closest;
};
const closestCity = findClosestCity(userLocation.lat, userLocation.lng, cityCoordinates);
console.log('Closest City:', closestCity);