Nyxynyx
Nyxynyx

Reputation: 63619

Travel from a point

I want to use Google Maps API to draw an area around a particular point on the map where a person can walk to within X minutes. In other words, how can you find all the places one can travel from a given point within a user defined period of time?

Upvotes: 14

Views: 683

Answers (2)

Cybercartel
Cybercartel

Reputation: 12592

Here is ready-to-copy solution: http://maps.forum.nu/gm_driving_radius.html#. An alternative near perfect solution is to use a space-filling-curve or a spatial-index. A sfc reduce the 2d complexity to a 1d complexity and it's an approximation algorithm not a heuristic. With a sfc it should be a guarantee of 1/4 to find all the points in the euklidian space.
enter image description here

Upvotes: 4

jamie-wilson
jamie-wilson

Reputation: 1925

Update: Have a play with this:

<!DOCTYPE html>
<html> 
<head> 
   <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
   <title>Google Maps Geometry</title> 
   <script src="http://maps.google.com/maps/api/js?sensor=false" 
           type="text/javascript"></script>

</head> 
<body> 
   <div id="map" style="width: 1000px; height: 800px"></div> 

   <script type="text/javascript"> 

   function CalculateDistanceBetweenTwoPoint(lat1, lon1, lat2, lon2) {

        var R = 6371; // km
        var dLat = (lat2-lat1).toRad();
        var dLon = (lon2-lon1).toRad();
        var lat1 = lat1.toRad();
        var lat2 = lat2.toRad();

        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 * 1000;

   }



      Number.prototype.toRad = function() {
         return this * Math.PI / 180;
      }

      Number.prototype.toDeg = function() {
         return this * 180 / Math.PI;
      }

      google.maps.LatLng.prototype.destinationPoint = function(brng, dist) {
         dist = dist / 6371;  
         brng = brng.toRad();  

         var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();

         var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) + 
                              Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));

         var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
                                      Math.cos(lat1), 
                                      Math.cos(dist) - Math.sin(lat1) *
                                      Math.sin(lat2));

         if (isNaN(lat2) || isNaN(lon2)) return null;

         return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
      }

      var pointA = new google.maps.LatLng(40.80, -74.00);   // Circle center
      var radius = 1;                                      // 10km

      var mapOpt = { 
         mapTypeId: google.maps.MapTypeId.TERRAIN,
         center: pointA,
         zoom: 17
      };

      var map = new google.maps.Map(document.getElementById("map"), mapOpt);

      // Draw the circle
      new google.maps.Circle({
         center: pointA,
         radius: radius * 1000,       // Convert to meters
         fillColor: '#FF0000',
         fillOpacity: 0.2,
         map: map
      });

      // Show marker at circle center
      new google.maps.Marker({
         position: pointA,
         map: map
      });

      var i = 0;
      setTimeout(LoopThroughPoints, 1000);


    var triangleCoords = [];

    function LoopThroughPoints() {


         var directionsService = new google.maps.DirectionsService();

            var destination = pointA.destinationPoint(i, radius);

          var request = {
              origin: pointA,
              destination: destination,
              travelMode: google.maps.TravelMode["WALKING"]
          };
          console.log(request);

          directionsService.route(request, function(response, status) {
        console.log(response);

            if (status == google.maps.DirectionsStatus.OK) {

                var cumulativeDistance = 0;

                new google.maps.Marker({
                            position: destination,
                            map: map
                        });


                loopy: for(var i = 0; i < response.routes[0].overview_path.length; i++)
                {

                    var path = response.routes[0].overview_path[i];
                    var pathNext = response.routes[0].overview_path[i+1];

                    cumulativeDistance += CalculateDistanceBetweenTwoPoint(path.Oa, path.Pa, pathNext.Oa, pathNext.Pa);

                    if(cumulativeDistance >= 500) {
                        triangleCoords.push(new google.maps.LatLng(path.Oa, path.Pa));
                        break loopy;                        
                    }

                }

            }
          });


        i = i + 10;
        if(i!=360) {

            setTimeout(LoopThroughPoints, 10);

        } else {
            bermudaTriangle = new google.maps.Polygon({
                paths: triangleCoords,
                strokeColor: "#FF0000",
                strokeOpacity: 0.8,
                strokeWeight: 2,
                fillColor: "#FF0000",
                fillOpacity: 0.35
            });

            bermudaTriangle.setMap(map);
        }


      }



   </script> 
</body> 
</html>

Just a quick look and some starters, though someone may be able to provide some better solutions.

There doesn't seem to be a way to get all the roads coming off a certain point with the Maps API.

Distance: Time taken is a hard one, I would try and calculate it in meters. So according to http://answers.yahoo.com/question/index?qid=1006021202308 (scientific i know…) 5km/h or 500m in 6 minutes.

My method would be:

This could also be helpful:

How to move a marker 100 meters with coordinates

Some more! Google Maps: Given a point, how to find all points at a given road distance?

This shows how to find all the points and then snap to the nearest street

Upvotes: 1

Related Questions