0

Im writing an app that has a ton of locations, all with coordinates, I want the app to be able to search for the locations by name, or by which one is closest. I know how to determine the distance between two coordinates via the haversine formula. However I want my app to go through each object(location) in an array and add a new element to that object called distance and distance should be the distance to the location from my location. I have the following code that I think should work but it doesn't. Does anyone have any ideas?

function GetLocation(location) {
    myLat = location.coords.latitude;
    myLon = location.coords.longitude;
    angular.forEach($scope.ASiteLocs, function(object, location) {
      location.Point.coordinates = location.Point.coordinates.substring(0, clength - 2).split(",");
      Lat = location.Point.coordinates[0];
      Lon = location.Point.coordinates[1];
      function getCoordDistance() {
        Number.prototype.toRad = function() {
          return this * Math.PI / 180;
        }

        var lat2 = myLat;
        var lon2 = myLon;
        var lat1 = Lat;
        var lon1 = Lon;

        var R = 3959; // Radius in miles 
        //has a problem with the .toRad() method below.
        var x1 = lat2 - lat1;
        var dLat = x1.toRad();
        var x2 = lon2 - lon1;
        var dLon = x2.toRad();
        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
          Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
          Math.sin(dLon / 2) * Math.sin(dLon / 2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        var d = R * c;

      }
      object.distance = d;
    });
  }

Here is what the locations look like(just a few of them):

"name": "502 Nelson St, Greenville, MS 38701",
    "visibility": "0",
    "description": "502 Nelson St, Greenville, MS 38701",
    "styleUrl": "#waypoint",
    "Point": {
      "coordinates": "-91.05636,33.415485,0"
    }
  }, {
    "name": "242 Blackhawk Trace, Galena, IL 61036",
    "visibility": "0",
    "description": "242 Blackhawk Trace, Galena, IL 61036",
    "styleUrl": "#waypoint",
    "Point": {
      "coordinates": "-90.319778,42.390862,0"
    }
  }, {
    "name": "3747 Ocean Dr, Vero Beach, FL 32963",
    "visibility": "0",
    "description": "3747 Ocean Dr, Vero Beach, FL 32963",
    "styleUrl": "#waypoint",
    "Point": {
      "coordinates": "-80.358248,27.659094,0"
    }
  }

Here is a plunk of my work if that makes it easier to read.
http://plnkr.co/edit/nRQc7Ym0lsaK6jQwd626?p=preview

Ian Pennebaker
  • 233
  • 4
  • 15

2 Answers2

0

When using angular.forEach for an array of objects, the first argument of the function is the object, the second the array index:

angular.forEach($scope.ASiteLocs, function(location, arrayIndex) {
    ...
    location.distance = d;
})

Note 1: you are changing the location.Point.coordinates from string to array in your forEach, so the GetLocation function will only work once because the original location array is changed.

Note 2: definining a function in a loop is bad practice and 'expensive'

Wenoud
  • 16
  • 1
0

Your code will be more cleaner if you use the my npm package haversine-calculator in your code:

const haversineCalculator = require('haversine-calculator')

const start = {
  latitude: -23.754842,
  longitude: -46.676781
}

const end = {
  latitude: -23.549588,
  longitude: -46.693210
}

console.log(haversineCalculator(start, end))
console.log(haversineCalculator(start, end, {unit: 'meter'}))
console.log(haversineCalculator(start, end, {unit: 'mile'}))
console.log(haversineCalculator(start, end, {threshold: 1}))
console.log(haversineCalculator(start, end, {threshold: 1, unit: 'meter'}))
console.log(haversineCalculator(start, end, {threshold: 1, unit: 'mile'}))
Undo
  • 25,519
  • 37
  • 106
  • 129