Stack Overflow Asked by SuryaN on November 4, 2021
I have an object which has 2 attributes – latitude and longitude. I want to get the nearest match from the object array by considering both attributes.
obj = {latitude: 55.87, longitude: 4.20}
[
{
"latitude": 55.85,
"longitude": 4.22
},
{
"latitude": 55.89,
"longitude": 4.16
},
{
"latitude": 55.88,
"longitude": -4.24
}
]
I need to get the array index which is closest match.
Use below code to get the index. I follow the same pattern as followed by @Meadow.
let points = [{
"latitude": 55.85,
"longitude": 4.22
},
{
"latitude": 55.89,
"longitude": 4.16
},
{
"latitude": 55.88,
"longitude": -4.24
},
{
"latitude": 55.86,
"longitude": 4.21
}
];
let allDistance:any = [];
points.forEach((x,index)=> {
var res = this.getDistance(x.latitude, x.longitude, 55.87, 4.20, "km");
allDistance.push({ distance: res, obj: x,index: index});
});
allDistance.sort((a, b) => a.distance - b.distance);
console.log("Index:"+allDistance[0].index);
console.log(allDistance);
Get Distance method:
getDistance(markerLat: any, markerLon: any, sourceLat: any, sourceLng: any,unit): any {
var radlat1 = Math.PI * sourceLat / 180;
var radlat2 = Math.PI * markerLat / 180;
var theta = sourceLng - markerLon;
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;
dist = dist * 1.609344;
if (unit != 'mi') {
return isNaN(dist) ? 0 : dist;
}
return isNaN(dist * 0.62137) ? 0 : dist * 0.62137;
}
Answered by surendra kumar on November 4, 2021
There's a Haversine formula to calculate spherical distance between your point and each point in array, e.g. using Array.prototype.reduce()
:
const haversine = ({longitude: lonA, latitude: latA}, {longitude: lonB, latitude: latB}) => {
const {PI, sin, cos, atan2} = Math,
r = PI/180,
R = 6371,
deltaLat = (latB - latA)*r,
deltaLon = (lonB - lonA)*r,
a = sin(deltaLat / 2)**2 + cos(cos(latB*r)*latA*r) * sin(deltaLon /2)**2,
c = 2 * atan2(a**0.5, (1 - a)**0.5),
d = R * c
return d
},
obj = {latitude: 55.87, longitude: 4.20},
arr = [{"latitude":55.85,"longitude":4.22},{"latitude":55.89,"longitude":4.16},{"latitude":55.88,"longitude":-4.24}],
{closest} = arr.reduce((r,o) => {
const distance = haversine(o, obj)
distance < r.minDistance || !r.closest &&
(r.closest = o, r.minDistance = distance)
return r
}, {closest: null, minDistance: null})
console.log(closest)
.as-console-wrapper{min-height:100%;}
Answered by Yevgen Gorbunkov on November 4, 2021
You can do this with JS. You can use this piece of code
export class ContentComponent implements OnInit {
compareTo: any = { latitude: 55.87, longitude: 4.20 };
data: Array<any> = [
{
"latitude": 55.85,
"longitude": 4.22
},
{
"latitude": 55.89,
"longitude": 4.16
},
{
"latitude": 55.88,
"longitude": -4.24
}
];
// data filtered
filteredData: Array<any> = [];
constructor() { }
ngOnInit() {
var tmpData: Array<any> = [];
this.data.forEach(x => {
var res = this.computeDistance(x.latitude, x.longitude, this.compareTo.latitude, this.compareTo.longitude, "K");
tmpData.push({ distance: res, obj: x });
});
tmpData.sort((a, b) => a.distance - b.distance);
tmpData.forEach(x => this.filteredData.push(x.obj));
}
computeDistance(lat1, lon1, lat2, lon2, unit) {
if ((lat1 == lat2) && (lon1 == lon2)) {
return 0;
}
else {
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;
}
}
}
Answered by Meadow on November 4, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP