我有一系列定位对象,其中GPS位置与这些对象绑定在一起。我想根据用户的当前位置过滤整个数组,并比较用户位置和位置对象之间的距离。
我有一个当前功能可以完成此任务,但是我知道这样做效率不高。与创建临时变量并每次将临时变量分配给数组相比,我更喜欢对数组进行过滤。
//sample data
public getLocation = [
{
"ID": "1",
"Name": "Test Location 1",
"Lat": "32.16347467",
"Lon": "-103.67178545"
}, {
"ID": "2",
"Name": "Test Location 2",
"Lat": "32.16347451",
"Lon": "-103.67178544"
}, {
"ID": "3",
"Name": "Test Location 3",
"Lat": "32.13559815",
"Lon": "-103.67544362"
}, {
"ID": "4",
"Name": "Test Location 4",
"Lat": "32.40144407",
"Lon": "-103.13168477"
}, {
"ID": "5",
"Name": "Test Location ",
"Lat": "32.14557039",
"Lon": "-103.67011361",
}
]
grabLocation(){
this.platform.ready().then(() => {
this.geolocation.getCurrentPosition().then((resp) => {
this.userLocation = [parseFloat(resp.coords.latitude.toFixed(4)),parseFloat(resp.coords.longitude.toFixed(4))];
this.userLocation = [resp.coords.latitude,resp.coords.longitude];
var getLocation
getLocation = this.asyncLocations.grabUserLoc(this.userLocation[0],this.userLocation[1]);
console.log(getLocation);
}).catch((error) => {
this.presentToast(error);
});
});
}
//asyncLocations.ts
grabUserLoc(lat,lon){
var tempLocation= [];
for(let i=0;i<this.getLocation.length;i++){
if((this.getLocation[i]['Lat']!="") && this.getLocation[i]['Lon']!=""){
let R = 6371;// km
let RinM = (R*0.621371);
let Lat1 = (parseFloat(lat.toFixed(5)));
let Lon1 = (parseFloat(lon.toFixed(5)));
let Lat2 = (parseFloat(this.getLocation[i]['Lat']));
let Lon2 = (parseFloat(this.getLocation[i]['Lon']));
let dLat = this.toRad(Lat2-Lat1);
let dLon = this.toRad(Lon2-Lon1);
let RLat1 = this.toRad(Lat1);
let RLat2 = this.toRad(Lat2);
let a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(RLat1) * Math.cos(RLat2);
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
//let d = R * c;
let e = RinM * c;
if(e < 5){
tempLocation.push(this.getLocation[i]);
}
}
}
this.getLocation = tempLocation;
return this.getLocation;
}
// Converts numeric degrees to radians
toRad(Value)
{
return Value * Math.PI / 180;
}
我目前正在检查5英里以外的位置。
任何帮助将不胜感激。
答案 0 :(得分:2)
不要将经纬度值存储为字符串-尽早将其转换为浮点数
将Haversine计算分离为自己的函数
考虑使用Haversine的余弦变量,并省略最后的acos
步骤
在循环外重构常量表达式
考虑预先计算纬度和经度的弧度等效值
另请参阅Quicker way to calculate geographic distance between two points
答案 1 :(得分:0)
我建议使用WebWorker,以便长时间不阻塞主UI线程,并且可以中断给定事件启发性的搜索/过滤器,并补充最新数据:-
importScripts("Tier3Toolbox.js");
var currVintage = 0;
var inBounds = false;
var facFilter = [];
var imageProlog = "<div style='height:5em; width:5em; display:inline-block;vertical-align:middle;'>" +
"<img style='height:100%; width: 100%; max-height:100%; max-width:100%' src='";
var imageEpilog = "' ></div>";
var facilityTable, lineBreak;
self.addEventListener('message', function(e)
{
var data = e.data;
switch (data.cmd) {
case 'init':
initThread(data.load);
break;
case 'initFilter':
for (var i=0; i<data.filterTable.length; i++) {
facFilter[data.filterTable[i].locTypeId] = {'icon':data.filterTable[i].icon};
}
break;
case 'filter':
facFilter = [];
for (var i=0; i<data.filterTable.length; i++) {
if (data.filterTable[i].facSelected)
facFilter[data.filterTable[i].locTypeId] = {'icon':data.filterTable[i].icon};
}
break;
case 'search':
var searchVintage = ++currVintage;
var tableSearch = new searcher(searchVintage, data);
break;
case 'reset':
reset();
self.postMessage({'reset': true});
break;
case 'stop':
self.postMessage({'success' : true});
self.close();
break;
default:
self.postMessage({'success' : false, 'msg' : data.msg});
};
}, false);
function initThread(msg)
{
facilityTable = JSON.parse(msg);
reset();
self.postMessage({'success' : true,
'cnt' : facilityTable.length
});
}
function reset()
{
for (var i=0; i<facilityTable.length; i++) {
facilityTable[i].visible=false
}
currVintage = 0;
}
function searcher(searchVintage, msg)
{
var myVintage = searchVintage;
var facIndex = -1;
var msg = msg;
var checkLoop = function()
{
if (myVintage != currVintage)
return;
if (++facIndex == facilityTable.length)
return;
inBounds = geoFencer.call(this, msg);
if (inBounds) {
var facMatch = 0;
var bubbleHTML = "";
for (var i=0; i<facilityTable[facIndex].facilities.length; i++){
var currFac = facilityTable[facIndex].facilities[i];
if (facFilter[currFac.locTypeId] != undefined) {
if (facMatch != 0) {
lineBreak = (facMatch / 3);
if (lineBreak == lineBreak.toFixed(0)) {
bubbleHTML += "<br />";
}
}
facMatch++;
bubbleHTML += imageProlog + facFilter[currFac.locTypeId].icon + imageEpilog;
}
}
if (facMatch == 0) {
inBounds = false;
}
}
if (inBounds != facilityTable[facIndex].visible) {
self.postMessage({'match' : inBounds,
'facIndex' : facIndex,
'scopeVintage': msg.scopeVintage,
'bubbleHTML' : bubbleHTML,
'success' : true
});
facilityTable[facIndex].visible = inBounds;
}
setTimeout(checkLoop,0);
}
var circleCheck = function(msg)
{
var diff = Tier3Toolbox.calculateDistance(
msg.centerLat,
msg.centerLng,
facilityTable[facIndex].searchLat,
facilityTable[facIndex].searchLng);
if (msg.radius > diff)
return true;
return false;
}
var rectangleCheck = function(msg)
{
if (facilityTable[facIndex].searchLat > msg.SWLat &&
facilityTable[facIndex].searchLat < msg.NELat &&
facilityTable[facIndex].searchLng > msg.SWLng &&
facilityTable[facIndex].searchLng < msg.NELng)
return true;
return false;
}
var GEOFENCER = [circleCheck,rectangleCheck];
var geoFencer = GEOFENCER[msg.checker];
setTimeout(checkLoop,0);
return this;
}