none
Search for a location within radius by using the Spatial Math Module - Search Pushpin within Radius functionality RRS feed

  • Question

  • Hello 

    I wish to use the Search Pushpin Within Radius functionality of the Spatial Math module in bing maps to look if a location is within a defined area or not.

    This area is eventually defined using radius. I thought of using the location's coordinate (latitude and longitude) as point of origin to calculate the distance between the pushpin locations and these coordinates; which I would later compare to the chosen radius.

    I tried to adapt the code to my needs as follows:

    <script type='text/javascript'>
        var map, pinLayer, searchPolygon;
        function GetMap() {
            map = new Microsoft.Maps.Map('#myMap', {
                credentials: 'Bing Map key',
                zoom: 12
            });
            //Add some random pushpins to a layer on the map.
            pinLayer = new Microsoft.Maps.Layer();
            map.layers.insert(pinLayer);
            var pushpins = Microsoft.Maps.TestDataGenerator.getPushpins(100, map.getBounds(), { color: 'purple' });
            pinLayer.add(pushpins);
            //Load the Spatial Math modules.
            Microsoft.Maps.loadModule('Microsoft.Maps.SpatialMath');
        }
    
        function Search() {
            //Use the center of the map as the center of the search area.
            var origin = map.getCenter();
    
            var latitude = document.getElementById("lat").value;
            var longitude = document.getElementById("lon").value;
    
           
            var lat = parseFloat(latitude);
            var lon = parseFloat(longitude);
    
            var latLon = new Microsoft.Maps.Location(lat, lon);
            alert(latLon);
    
            var radiusOption = document.getElementById("radiusOption");
            var radius = parseFloat(radiusOption.options[radiusOption.selectedIndex].text);
    
            //Get all the pushpins from the pinLayer.
            var pins = pinLayer.getPrimitives();
    
            for (var i = 0; i < pins.length; i++) {
                var distance = Microsoft.Maps.SpatialMath.getDistanceTo(latLon, pins[i].getLocation(), Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers);
                if (distance <= radius) {
                    pins[i].setOptions({ color: 'red' });
                } else {
                    pins[i].setOptions({ color: 'purple' });
                }
            }
    
            //var circleLocs = Microsoft.Maps.SpatialMath.getRegularPolygon(origin, radius, 36, Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers);
    
            //Create a circle polygon to show the search area.
            var circleLocs = Microsoft.Maps.SpatialMath.getRegularPolygon(latLon, radius, 36, Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers);
            if (searchPolygon) {
                searchPolygon.setLocations(circleLocs);
            } else {
                searchPolygon = new Microsoft.Maps.Polygon(circleLocs, {
                    strokeColor: 'red',
                    fillColor: 'transparent'
                });
                map.entities.push(searchPolygon);
            }
        }
    
    </script>
    
    <script type='text/javascript' src='http://www.bing.com/api/maps/mapcontrol?callback=GetMap' async defer></script>

    And I have the HTML part :

    <div class="row">
        </br>
        <div class="col-lg-3">
            <label>Radius (KM): </label>
            <select id="radiusOption" class="form-control">
                <option>1</option>
                <option selected="selected">5</option>
                <option>10</option>
                <option>15</option>
            </select>
        </div>
        <div class="col-lg-3">
            <label>Latitude: </label>
            <input type="text" class="form-control" name="latitude" id="lat" value="4.1546" />
        </div>
    
        <div class="col-lg-3">
            <label>Longitude: </label>
            <input type="text" class="form-control" name="longitude" id="lon" value="9.23662" />
        </div>
    
        <div class="col-lg-2"><input type="button" class="btn btn-primary" onclick="Search()" value="Search" /></div>
    </div><br />
    
    <div class="row">
        <div class="col-lg-12" id="myMap" style=";width:800px;height:500px;"></div>
    </div>
    
    <div id="outputPanel"></div>


    I already succeed in getting the coordinates (latitude and longitude) entered by the user in the HTML input boxes and pass them to the JavaScript.

    But my difficulty lies on how to calculate the distance between the pushpins and the location(which would serve as my point of origin).


    Code is passion!


    • Edited by nicekloe Tuesday, February 26, 2019 7:59 AM
    Tuesday, February 26, 2019 7:52 AM

All replies

  • Hi Nicekloe,

    For the question "how to calculate the distance between the pushpins and the location" there are special math APIs that can help.  Take a look at http://bingmapsv8samples.azurewebsites.net/#Basics%20Spatial%20Math%20Functions and https://www.bing.com/api/maps/sdk/mapcontrol/isdk/distancebetweentwolocations

    Sincerely,

    IoTGirl

    Monday, March 4, 2019 8:28 PM
    Owner
  • Thanks IoTGirl for your response

    I could advance with my code and get to a pretty good level. Actually, this is what I can do for the Search within radius functionality :

    - Get a location typed by a user in the location bar (as well as the coordinates of the location). This serves as my point of origin for calculations

    - Get the radius selected by user

    - Get all the locations found in my database

    - Calculate the distance between these locations and the origin and compare to the selected radius

    - Display a red pushpin if the distance is less than the radius and a purple pushpin inversely

    Below is my code:

    <script type='text/javascript'>
        var map, searchManager, searchPolygon;
        var arrayLocations = [];
        var locs = [];
    
        function GetMap() {
            map = new Microsoft.Maps.Map('#myMap', {});
            Microsoft.Maps.loadModule(['Microsoft.Maps.AutoSuggest', 'Microsoft.Maps.Search'], function () {
                var manager = new Microsoft.Maps.AutosuggestManager({ map: map });
                manager.attachAutosuggest('#searchBox', '#searchBoxContainer', suggestionSelected);
                searchManager = new Microsoft.Maps.Search.SearchManager(map);
            });
    
            //Load the Spatial Math modules.
            Microsoft.Maps.loadModule('Microsoft.Maps.SpatialMath');
        }
    
        function suggestionSelected(result) {
            //Remove previously results from the map.
            map.entities.clear();
            //Show the suggestion as a pushpin and center map over it.
            var pin = new Microsoft.Maps.Pushpin(result.location);
            map.entities.push(pin);
            map.setView({ bounds: result.bestView });
            document.getElementById('output').innerHTML = 'Selection:<br/>' + result.name;
        }
    
        //function geocode selected address and search
        function geocode() {
            //Remove previously results from the map.
            map.entities.clear();
            //Get the users query and geocode it.
            var query = document.getElementById('searchBox').value;
            var searchRequest = {
                where: query,
                callback: function (r) {
                    if (r && r.results && r.results.length > 0) {
                        var pin, pins = [], output = 'Results:<br/>';
    
                        //Add a pushpin for each result to the map and create a list to display.
                        for (var i = 0; i < r.results.length; i++) {
                            //Create a pushpin for each result.
                            pin = new Microsoft.Maps.Pushpin(r.results[i].location, {
                                text: i + ''
                            });
                            //Adding pins to list
                            pins.push(pin);
                            locs.push(r.results[i].location);
                            output += i + ') ' + r.results[i].name + '<br/>';
                        }
                        //alert(locs);
    
    
                        //As from here starts the search algorithm
                        //Define a center point and get the selected radius
                        alert("bonjour eunice");
                        var origin;
                        for (i = 0; i < locs.length; i++) {
                            origin = locs[0];
                        }
                        //alert(origin);
    
                        var radiusOption = document.getElementById("radiusOption");
                        var radius = parseFloat(radiusOption.options[radiusOption.selectedIndex].text);
                        //alert(radius);
    
                        //Get all locations from DB
                        $.ajax({
                            url: 'http://localhost:53851/Locations/ReturnLocationsList',
                            type: 'POST',
                            dataType: 'json',
                            success: function (response) {
                                //do something with data
                                //alert(JSON.stringify(response.data));
                                arrayLocations = response.data;
                                //alert(arrayLocations.length);
                                var columns = ['IdLocation', 'Name', 'Latitude', 'Longitude'];
    
                                //Add pushpin to origin
                                var pinOrigin = new Microsoft.Maps.Pushpin(origin, {
                                    color: 'blue'
                                });
                                map.entities.push(pinOrigin);
    
                                //Convert gotten locations to Maps.Locations in order to ease calculations
                                var allLocations = [];
                                alert("are you here ?");
    
                                for (i = 0; i < arrayLocations.length - 1; i++) {
                                    var coordinates = new Microsoft.Maps.Location(arrayLocations[i].Latitude, arrayLocations[i].Longitude);
                                    allLocations.push(coordinates);
                                }
                                alert(allLocations[0]);
    
                                //Search if the locations contained in database are within radius
                                //Loop through each location and calculate its distance from the origin and change the color depending on if it is within the search area or not.
                                alert(allLocations.length);
                                for (var i = 0; i < allLocations.length; i++) {
                                    //Create custom Pushpin for each location
                                    alert("did you reach here?");
                                    var pin = new Microsoft.Maps.Pushpin(allLocations[i]);
                                    alert(allLocations[i]);
                                    var distance = Microsoft.Maps.SpatialMath.getDistanceTo(origin, allLocations[i], Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers);
                                    alert(distance);
                                    if (distance <= radius) {
                                        pin.setOptions({ color: 'red' });
                                    } else {
                                        pin.setOptions({ color: 'purple' });
                                    }
                                }
    
                                //Add the pins to the map
                                map.entities.push(pin);
    
                                //Create a circle polygon to show the search area.
                                var circleLocs = Microsoft.Maps.SpatialMath.getRegularPolygon(origin, radius, 36, Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers);
                                if (searchPolygon) {
                                    searchPolygon.setLocations(circleLocs);
                                    alert("there are no circleLocs");
                                } else {
                                    searchPolygon = new Microsoft.Maps.Polygon(circleLocs, {
                                        strokeColor: 'red',
                                        fillColor: 'transparent'
                                    });
                                    alert("there are circleLocs");
                                    map.entities.push(searchPolygon);
                                }
    
                            },
                            error: function (error) {
                                //log or alert the error
                                alert("There's an error !");
                                //alert(error);
                            }
                        });
    
    
                        //Display list of results
                        document.getElementById('output').innerHTML = output;
                        //Determine a bounding box to best view the results.
                        var bounds;
                        if (r.results.length == 1) {
                            bounds = r.results[0].bestView;
                        } else {
                            //Use the locations from the results to calculate a bounding box.
                            bounds = Microsoft.Maps.LocationRect.fromLocations(locs);
                        }
                        map.setView({ bounds: bounds, padding: 30 });
                    }
                },
                errorCallback: function (e) {
                    document.getElementById('output').innerHTML = "No results found.";
                }
            };
            //Make the geocode request.
            searchManager.geocode(searchRequest);
        }
    </script>
    <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[Bing Map Key]' async defer></script>

    The HTML code:

    <div class="row">
        <div class="col-lg-12" style="margin-top:30px;" id='searchBoxContainer'>
            <div class="col-lg-3">
                <label>Type a place: </label>
                <input type='text' class="form-control" id='searchBox' />
            </div>
    
            <div class="col-lg-3">
                <label>Radius (KM): </label>
                <select id="radiusOption" class="form-control">
                    <option>1</option>
                    <option selected="selected">5</option>
                    <option>10</option>
                    <option>15</option>
                    <option>20</option>
                    <option>25</option>
                    <option>30</option>
                </select>
            </div>
    
            <div class="col-lg-3">
                <input type='button' class="btn btn-primary" value='Search' onclick='geocode()' />
            </div>
        </div>
    </div>
    <br />
    <div class="row col-lg-12">
        <div id="myMap" style=";width:800px;height:450px;"></div>
    </div>
    
    <div id='output' style="margin-left:10px;float:left;"></div>

    I have a problem displaying the circle which indicated the search area. At the level of the if condition which determines if "searchPolygon" is true or false, the alert message "there are circleLocs" displays, but with no circle around the search area. I don't know where I'm going wrong.

    Please, some help will be greatly appreciated.


    Code is passion!

    Wednesday, March 6, 2019 5:31 PM