Direction api: check if a place falls in the route

2019-01-14 04:15发布

问题:

I am using Google Direction API to plot the route path between 2 places A and B. I am able to do this. Now, I have a requirement to check if given a place C falls in the route path of A and B.

Here is the snapshot of the route path that I have generated from my code.

Here is the corresponding code:

function initialize() {
                var input = document.getElementById('searchTextFieldSource');
                var input1 = document.getElementById('searchTextFieldDestination');

                var autocomplete = new google.maps.places.Autocomplete(input);
                var autocomplete1 = new google.maps.places.Autocomplete(input1);
                google.maps.event.addListener(autocomplete1, 'place_changed', function () {
                    var place = autocomplete.getPlace();
                    document.getElementById('city1').value = place.name;
                    var place1Lat = place.geometry.location.lat();
                    var place1Lng = place.geometry.location.lng();
                    document.getElementById('cityLat1').value = place1Lat;
                    document.getElementById('cityLng1').value = place1Lng;

                    var obj = new Object();
                    obj.city =place.name;
                    obj.latitude = place.geometry.location.lat();
                    obj.longitude = place.geometry.location.lng();
                    locations.push(obj);


                    var place2 = autocomplete1.getPlace();
                    document.getElementById('city2').value = place2.name;
                    var place2Lat = place2.geometry.location.lat();
                    var place2Lng = place2.geometry.location.lng();
                    document.getElementById('cityLat2').value = place2Lat;
                    document.getElementById('cityLng2').value = place2Lng;

                    var obj = new Object();
                    obj.city = place2.name;
                    obj.latitude = place2.geometry.location.lat();
                    obj.longitude = place2.geometry.location.lng();
                    locations.push(obj);

                    directionsDisplay = new google.maps.DirectionsRenderer();
                    var startPlace = new google.maps.LatLng(place1Lat, place1Lng);

                    var mapOptions = {
                        zoom:7,
                        center: startPlace
                    }

                    var map = new google.maps.Map(document.getElementById('map'), mapOptions);
                    directionsDisplay.setMap(map);
                    //refreshMap(locations);

                    var start = $("#city1").val();
                    var end = $("#city2").val();
                    var request = {
                          origin:start,
                          destination:end,
                          travelMode: google.maps.TravelMode.DRIVING
                    };
                    directionsService.route(request, function(response, status) {
                        if (status == google.maps.DirectionsStatus.OK) {
                          directionsDisplay.setDirections(response);
                        }
                    });
                });
            }

How can I go about it?

回答1:

You can use the geometry library that (you can request with google maps by changing your script src to https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry) and use isLocationOnEdge and use the LatLng of point C and the polyline that is returned from the DirectionsService.

https://developers.google.com/maps/documentation/javascript/geometry#isLocationOnEdge

Then again, point C could ALWAYS be on the way between A and B if you added it as a waypoint, so determining if point C is "on the way" is actually a bit of a tricky concept - how far out of the way is too far for it to not be "on the way"?



回答2:

Hi @Adam and @Adarsh Konchady I have followed same approach as suggested in these discussion's. Still I am unable to locate the point on same route (though it is geographically present). Below is my code. I request you to please review attached code and let me know if I am doing something wrong.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Directions service</title>
    <style>
		html, body {
		  height: 100%;
		  margin: 0;
		}
		
		#map {
		  height: 50%;
		  width: 50%;
		}
		
		.map-center {
			border: solid 1px black;
			position: absolute;
			left: 50%;
			top: 60%;
			background-color: white;
			z-index: 100;

			height: 400px;
			margin-top: -200px;

			width: 600px;
			margin-left: -300px;
		}

		#source {
		  width: 50%;
		  height: 25px;
		}

		#destination {
		  width: 50%;
		  height: 25px;
		}
		
		#customerSource {
		  width: 50%;
		  height: 25px;
		}
    </style>
  </head>
  <body>
	<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places,geometry"></script>
	<script src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/routeboxer/src/RouteBoxer.js"></script>
    <script>
		var sourceLat, sourceLng;
		var destinationLat, destinationLng;
		function initialize() {

			var directionsDisplay = new google.maps.DirectionsRenderer();
			var directionsService = new google.maps.DirectionsService();
			var map;
			var routeBoxer = new RouteBoxer();
			var distance = 1;
			var cascadiaFault;
			var routeBounds = [];

			var mapOptions = {
				center: new google.maps.LatLng(37.7831,-122.4039),
				zoom: 12,
				mapTypeId: google.maps.MapTypeId.ROADMAP
			};

			var map = new google.maps.Map(document.getElementById('map'), mapOptions);

			directionsDisplay.setMap(map);

			var source = new google.maps.places.Autocomplete(document.getElementById('source'));
			var infoWindow = new google.maps.InfoWindow();
			var marker = new google.maps.Marker({
			  map: map
			});

			google.maps.event.addListener(source, 'place_changed', function() {
			  infoWindow.close();
			  var place = source.getPlace();
			  marker.setPosition(place.geometry.location);
			  sourceLat = marker.getPosition().lat();
			  sourceLng = marker.getPosition().lng();
			  infoWindow.setContent('<div><strong>' + place.name + '</strong><br>');
			});

			var destination = new google.maps.places.Autocomplete(document.getElementById('destination'));
			var infoWindow = new google.maps.InfoWindow();
			var marker = new google.maps.Marker({
			  map: map
			});

			google.maps.event.addListener(destination, 'place_changed', function() {
			  infoWindow.close();
			  var place = destination.getPlace();
			  marker.setPosition(place.geometry.location);
			  destinationLat = marker.getPosition().lat();
			  destinationLng = marker.getPosition().lng();
			  infoWindow.setContent('<div><strong>' + place.name + '</strong><br>');

				//Same event, draw route
			    var start = new google.maps.LatLng(sourceLat, sourceLng);
				var end = new google.maps.LatLng(destinationLat, destinationLng);
				var request = {
					origin: start,
					destination: end,
					travelMode: google.maps.TravelMode.DRIVING
				};
				directionsService.route(request, function(response, status) {
					if (status == google.maps.DirectionsStatus.OK) {
						directionsDisplay.setDirections(response);
						directionsDisplay.setMap(map);
						
						// Box around the overview path of the first route
					    var path = response.routes[0].overview_path;
					    var boxes = routeBoxer.box(path, distance);
						var pathsTemp = [];
						for (var i = 0; i < boxes.length; i++) {
							var bounds = boxes[i];
							// Perform search over this bounds
							pathsTemp.push(bounds.getCenter());
							routeBounds.push(bounds);
						}
						var temp = {}
						cascadiaFault = new google.maps.Polyline({
							paths: pathsTemp
						 });
						//alert(pathsTemp);
						//alert(cascadiaFault.getPath());
					} else {
						alert("Directions Request from " + start.toUrlValue(6) + " to " + end.toUrlValue(6) + " failed: " + status);
					}
				});
			});

			var customerSource = new google.maps.places.Autocomplete(document.getElementById('customerSource'));
			var infoWindow = new google.maps.InfoWindow();
			var marker = new google.maps.Marker({
			  map: map
			});

			google.maps.event.addListener(customerSource, 'place_changed', function() {
			  infoWindow.close();
			  var place = customerSource.getPlace();
			  marker.setPosition(place.geometry.location);
			  sourceLat = marker.getPosition().lat();
			  sourceLng = marker.getPosition().lng();
			  infoWindow.setContent('<div><strong>' + place.name + '</strong><br>');
			});
			
			google.maps.event.addDomListener(document.getElementById('search'), 'click', function searchLocation() {
			  alert(cascadiaFault);
			  if(google.maps.geometry.poly.isLocationOnEdge(customerSource.getPlace().geometry.location, cascadiaFault)) {
				alert("On the way..!!");
			  } else {
				alert("Not on the way..!!");
			  }
			  alert(routeBounds);
			  alert(customerSource.getPlace().geometry.location);
			});

		}
		
		google.maps.event.addDomListener(window, "load", initialize);

    </script>
	<b>Ride</b><br>
	<table>
		<col width="150">
		<col width="1000">
		<tr>
			<td>Source</td>
			<td><input type="text" id="source"></td>
		</tr>
		<tr>
			<td>Destination</td>
			<td><input type="text" id="destination"></td>
		</tr>
	</table>
	<b>Customer</b><br>
	<table>
		<col width="150">
		<col width="1000">
		<tr>
			<td>Customer Source</td>
			<td><input type="text" id="customerSource"><input type="button" id="search" value="Search" /></td>
		</tr>
		<tr>
			<td>Customer Destination</td>
			<td><input type="text" id="customerDestination"></td>
		</tr>
	</table>
	<div id="map" class="map-center"></div>
  </body>
</html>