micutzuclau
micutzuclau

Reputation: 27

How to check if markers are within circle radius without using Google Maps API, through PHP / CodeIgniter

I am using Google Maps to develop a app using Code Igniter, and I have a big issue with feature of checking if the coordonates of a marker are within the radius of a circle which is stored in my database.

I will try to describe in pseudocode, and sorry I'm a rookie.

  1. Right click-> a circle appears on the google map with a InfoBubble where you complete name, color and circle radius in meters;

  2. Click save-> Using ajax I send the circle center, name, color, etc.

  3. In the AJAX I am storing in the database the information about the circle, but before registering I need to set the number of markers that are found within the radius of the created circle.

I have searched and found this link http://www.movable-type.co.uk/scripts/latlong.html , but my math is not that great.

I need a function that takes the circle, marker coords and radius and that returns true or false if the marker is within the circle or not.

I made something that I found over the net but it does not work

public function arePointsNear($checkPoint, $centerPoint, $km) {
   $km = $km * 1000;
   $ky = 40000 / 360;
   $kx = cos(pi() * $centerPoint->lat / 180.0) * $ky;
   $dx = abs($centerPoint->lng - $checkPoint->lng) * $kx;
   $dy = abs($centerPoint->lat - $checkPoint->lat) * $ky;

   return sqrt($dx * $dx + $dy * $dy) <= $km;
}

Thanks!

Upvotes: 0

Views: 3520

Answers (1)

Emmanuel Delay
Emmanuel Delay

Reputation: 3679

Let me give you code that calculates that in Javascript; all within the Google Maps code, but the function that calculates the distance is just a function, not a service. (I don't know who wrote the function)

Your question is to have a PHP function, right? No doubt you can translate the javascript function to PHP; or you just trust the calculation in javascript and send that result with Ajax.

The code draws a Circle (center = Brussels; radius = 30km) and 4 markers. You can drag them all. Clicking on the button triggers the calculation. I show the result by turning the markers green or red.

(Do you know how to take over from here?)

<style>
  #map-canvas {
    height: 400px;
    margin: 0px;
    padding: 0px;
  }
</style>
<div id="map-canvas"></div>
<input type="button" id="start" value="Click">
<p>Drag the circle, drag the markers; when you click the button it will calculate if the markers are in the circle</p>

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?"></script>
<script>
  function initialize() {
    // settings
    var center = new google.maps.LatLng(50.84546, 4.357112);
    var radius_circle = 30000; // 30km
    var markerPositions = [
      {lat: 50.940749, lng: 4.2033035},
      {lat: 50.791671, lng: 4.587825},
      {lat: 50.66649, lng: 3.945124},
      {lat: 50.429139, lng: 4.813044}
    ];

    var markers=[];
    // draw map
    var mapOptions = {
      center: center,
      zoom: 8,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    var circle = drawCircle(mapOptions.center, radius_circle);

    // markers
    for (var i=0; i<markerPositions.length; i++) {
      markers.push(
        new google.maps.Marker({
          position: new google.maps.LatLng(markerPositions[i].lat, markerPositions[i].lng),
          map: map,
          draggable: true
        })
      );
    }

    // client clicks on button, we will check for the markers within the circle
    google.maps.event.addDomListener(document.getElementById('start'), 'click', function() {
      for (var i=0; i<markerPositions.length; i++) {
        var distance = calculateDistance(
          markers[i].getPosition().lat(),
          markers[i].getPosition().lng(),
          circle.getCenter().lat(),
          circle.getCenter().lng(),
          "K"
        );
        if (distance * 1000 < radius_circle) {  // radius is in meter; distance in km
          markers[i].setIcon('http://maps.gstatic.com/mapfiles/icon_green.png');      // make or find a better icon
        }
        else {
          markers[i].setIcon('http://maps.gstatic.com/mapfiles/icon.png');            // make or find a better icon
        }
      }
    });

    function drawCircle(center, radius) {
      return new google.maps.Circle({
        strokeColor: '#0000FF',
        strokeOpacity: 0.7,
        strokeWeight: 1,
        fillColor: '#0000FF',
        fillOpacity: 0.15,
        draggable: true,
        map: map,
        center: center,
        radius: radius
      });
    }

    function calculateDistance(lat1, lon1, lat2, lon2, unit) {
      var radlat1 = Math.PI * lat1/180;
      var radlat2 = Math.PI * lat2/180;
      var radlon1 = Math.PI * lon1/180;
      var radlon2 = Math.PI * lon2/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);
      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;
    }

  }
  google.maps.event.addDomListener(window, 'load', initialize);
</script>

Upvotes: 4

Related Questions