我正在尝试找到有人正在使用我的应用程序的正确建筑。现在我设法做了一个非常糟糕的过滤,我需要改进它。
我的目标是过滤将最近的建筑物返回给使用该应用程序的人,因此尽可能过滤它,而不会在同一建筑物中移动时产生错误。
我的fetch返回一个如下所示的api JSON数组:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
body {
background-color: black;
color: white;
}
</style>
</head>
<body>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
<p>hello</p>
</body>
</html>
这是我的代码
{
"data": [
{
"id": 1,
"city": "CITY",
"building_name": "Building 1",
"building_address": "Address 123",
"latitude": "57.7052809",
"longitude": "16.9367817"
},
{
"id": 2,
"city": "CITY",
"building_name": "Building 2",
"building_address": "Address 456",
"latitude": "35.7054509",
"longitude": "16.9366141"
}
],
}
答案 0 :(得分:2)
使用两点之间的“距离”来找到最近的点。您不能保证用户的建设,但您可以保证哪一个最接近用户的坐标。
var keys = Object.entries(data.data).map(([inst, key]) => key);
var returnedBuilding =
keys.reduce((prevCord, thing) => {
var dist = getDistance(userCoordinates.latitude, userCoordinates.longitude, thing.latitude, thing.longitude);
var prevDist = getDistance(userCoordinates.latitude, userCoordinates.longitude, prevCord.latitude, prevCord.longitude);
return dist < prevDist? thing : prevCord;
}, keys[0]);
以下是我从this post引用的getDistance函数。但是你可以编写自己的,更简单的,因为你只处理小距离(我假设)。
function getDistance(lat1, lon1, lat2, lon2)
{
var R = 6371; // km
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
var lat1 = toRad(lat1);
var lat2 = toRad(lat2);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
// Converts numeric degrees to radians
function toRad(Value)
{
return Value * Math.PI / 180;
}
答案 1 :(得分:1)
您可以使用haversine公式来确定哪个建筑物最接近。
根据经度和纬度,半球公式确定球体上两点之间的大圆距离。 tl; dr,你可以这样做,找到你自己和建筑物之间的距离,然后准确地确定哪个是最接近的。
这是SO的另一篇关于在javascript中使用它的文章: Using the Haversine Formula in Javascript
答案 2 :(得分:0)
您可以遍历每个建筑物并根据距离
找到最近的建筑物var closestBuilding = building[0];
var closestDistance = distanceFrom(user, building);
building.forEach(function(building) {
var distanceFrom = distanceFrom(user, building);
if(closestDistance > distanceFrom){
closestBuilding = building;
closestDistance = distanceFrom;
}
})
console.log(closestBuilding);
function distanceFrom(user, building) { /* your distance code */ }
答案 3 :(得分:-1)
我强烈建议您考虑更改数据模型以利用存储在mongoDB数据库中的GeoJSON点。这将允许您利用mongoDB强大的内置geospatial queries。使用上面的现有数据模型作为起点,您的新数据模型可能如下所示:
{
"id": 1,
"city": "CITY",
"building_name": "Building 1",
"building_address": "Address 123",
"location": {
"type": "Point",
"coordinates": [ // IMPORTANT: note the order is longitude, latitude
16.9367817, // longitude
57.7052809, // latitude
]
}
}
上面对象中的location属性是GeoJSON点。现在,您不是从数据库中获取每个位置并在客户端自己进行计算,而是查询建筑物数据库中最近的建筑物到用户的位置。假设用户坐标为latitude: 35.7053509
,longitude: 16.9362301
,您的查询可能看起来像这样(通过GET请求):
http://localhost:8888/api/buildings?lat=35.7053509&lng=16.9362301&maxDistance=2000
mongoDB文档提供了有关如何处理地理空间查询的示例。此示例取自文档,是您的api处理请求的方式:
// If you're using express.js, pull the params off the query object
const { lat, lng, maxDistance } = req.query;
const buildings = db.buildings.find(
{
location:
{
$near:
{
$geometry: { type: "Point", coordinates: [lng, lat] },
$maxDistance: maxDistance
}
}
}
)
.then(buildings => res.json({ buildings })) // respond to the client
.catch(err => console.log(err)) // do something with the error
来自您服务器的响应将是指定maxDistance
内所有建筑物的列表,按用户位置(距离最近)的距离排序。 MongoDB地理空间查询非常快速且高效。您甚至可以从db.find
操作切片第一个结果,如果您的客户只想要一个结果,则从您的api返回一个建筑物。
希望这有意义并且有所帮助!如果你没有使用过mongoDB和/或geoJSON对象,那么最初可能看起来有点令人生畏,但相信我,这将使你的生活变得更加容易。当您设置数据库和集合时,可能会发生另一个小问题。您需要确保在建筑物集合中添加索引以支持地理空间查询。来自文档:
db.buildings.createIndex( { location: "2dsphere" } )
然后创建您的收藏并将建筑文档添加到其中。
如果您需要任何澄清,请随时跟进。我建议您阅读mongoDB的文档并在线搜索更多示例。