none
Get the coordinates(latitude and longitude) of all the vertices or points of a drawn polygon on a map RRS feed

  • Question

  • Hi there,

    I'm setting up a small app which will permit an end user to draw a polygon on a map and the app gets all the coordinates(latitude and longitude) of the polygon. Then i'll fill two lists with these coordinates (one containing latitudes and the other containing longitudes), perform a search in each of these lists to know if a given set of points (for a location) belong to the selected area or not.

    So far I've used the drawingTools of BM Modules, V8 to enable drawing on a map. But I'm stuck at the level of getting the coordinates of the vertices of the polygon and do not know how to continue so far.

    This is the code I actually have :

    <script type='text/javascript'>
        var map, drawingManager;
    
        function GetMap() {
            map = new Microsoft.Maps.Map('#myMap', {});
    
            //Load the DrawingTools module
            Microsoft.Maps.loadModule('Microsoft.Maps.DrawingTools', function () {
                //Create an instance of the DrawingTools class and bind it to the map.
                var tools = new Microsoft.Maps.DrawingTools(map);
                //Show the drawing toolbar and enable editing on the map.
                tools.showDrawingManager(function (manager) {
                    //Store a reference to the drawing manager as it will be useful later.
                    drawingManager = manager;
                    //Create a shortcut to the DrawingBarAction to minimize code.
                    var da = Microsoft.Maps.DrawingTools.DrawingBarAction;
                    //Limit which tools appear in the drawing toolbar.
                    manager.setOptions({
                        drawingBarActions: da.polyline | da.polygon | da.erase,
                        fillColor: 'rgba(255, 0, 0, 0.5)'
                    });
                });
            });
        }
    
        function getShapes() {
            //var shapes = manager.getPrimitives();
            var shapes = drawingManager.getPrimitives();
            if (shapes && shapes.length > 0) {
                alert('Retrieved ' + shapes.length + ' from the drawing manager.');
    
                //Get the locations of the polyline/polygon.
                var locs = shapes.getLocations();
    
                //Loop through and display every coordinate in the drawing area
                for (i = locs.length - 1; i >= 0; i--) {
    
                    alert(locs[i]);
                }
    
            } else {
                alert('No shapes in the drawing manager.');
            }
        }
    </script>
    <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[Your-key-here]' async defer></script>
    
    
    <div class="row">
        <div class="col-lg-12">
            <div id="myMap" style=";width:950px;height:600px;"></div>
            <input type="button" class="btn btn-primary" value="Get Shapes" onclick="getShapes()" />
        </div>
    </div>

    Please, any link/sample code on how I can get these coordinates to proceed?

    Wednesday, February 13, 2019 9:29 AM

Answers

  • Intersection is actually used in sample code that I shared link for, have you looked into that example?
    Still you can check other method that I mentioned: intersects - Determines if two shapes intersect or not.

    It looks like code that you’re trying to use was written for old v6.3 map control:
    http://msdn.microsoft.com/en-us/library/cc451895.aspx#polygon-search
    when there was no Spatial Math functionality. Have you tried to debug it? Does it return any value for example for points[i].Longitude? Check points array, this is an array within array, if you still want to use this code you could add below in the first line under your pointInPolygon function:
    points = points[0].slice()
    And also make sure to change all Longitude and Latitude to longitude and latitude.
    However I would advise to use Spatial Math module instead.

    • Proposed as answer by S1mon_Moderator Thursday, February 21, 2019 4:59 PM
    • Edited by S1mon_Moderator Thursday, February 21, 2019 5:02 PM
    • Marked as answer by nicekloe Tuesday, February 26, 2019 7:43 AM
    Thursday, February 21, 2019 4:59 PM
    Moderator

All replies

  • Hi niceloe,

    If you look at the documentation for getLocation (https://docs.microsoft.com/en-us/bingmaps/v8-web-control/map-control-api/polygon-class) you will see it returns a collection of Location[].  

    Your code should look something like:

                //Loop through and display every coordinate in the drawing area
                for (i = locs.length - 1; i >= 0; i--) {
    
                    alert(locs[i].toString); // locs[I].Latitude and locs[I].Longitude hold the numberic values
    
                }

    Sincerely,

    IoTGirl


    Wednesday, February 13, 2019 6:22 PM
    Owner
  • Thanks IoTGirl for your response

    But I can't succeed in seeing the locations displayed on the screen. This is the javascript code I have :

     function getShapes() {
            //var shapes = manager.getPrimitives();
            var shapes = drawingManager.getPrimitives();
            if (shapes && shapes.length > 0) {
                alert('Retrieved ' + shapes.length + ' from the drawing manager.');
    alert("morning nicekloe");
    
                //Get the locations of the polyline/polygon.
                var locations = shapes.getLocations();
                alert("morning nicekloe2");
    
                //Loop through and display every coordinate in the drawing area
                for (i = locations.length - 1; i >= 0; i--) {
                    alert(locations[i].toString); // locs[I].Latitude and locs[I].Longitude hold the numberic values
    
                }
    
            } else {
                alert('No shapes in the drawing manager.');
            }
        }

    I actually succeed in displaying the 

    alert("morning nicekloe");

    but not the 

    alert("morning nicekloe2");

    which is located after the 

    var locations = shapes.getLocations();

    I'm pretty sure the typo should be here, but can't figure out what's going wrong.

    Please, any help?

    Thursday, February 14, 2019 10:48 AM
  • As noted in documentation getPrimitives() - Gets an array of shapes that are in the layer. This can be used to iterate over the individual shapes.

    So instead of
    var locations = shapes.getLocations();
    get locations for each individual shape
    var locations=[];
    for (i=0; i<shapes.length; i++){
     locations.push(shapes[i].getLocations())
    }



    Thursday, February 14, 2019 3:25 PM
    Moderator
  • Thanks for your response IoTGirl

    Now, I suceed in getting the coordinates of a drawn polygon. 

    coordinates of polygon drawn on mapMy quest now is to succeed in determining if a point(latitude, longitude) coming from the database lies within the drawn shape or not.

    I found this code on the Ray-casting method to know if a point lies within  a polygon or not

    function pointInPolygon(points,lat,lon) 
    {
      var i;
      var j=points.length-1;
      var inPoly=false;
    
      for (i=0; i<points.length; i++) 
      {
        if (points[i].Longitude<lon && points[j].Longitude>=lon 
          || points[j].Longitude<lon && points[i].Longitude>=lon) 
        {
          if (points[i].Latitude+(lon-points[i].Longitude)/ 
            (points[j].Longitude-points[i].Longitude)*(points[j].Latitude 
              -points[i].Latitude)<lat) 
          {
            inPoly=!inPoly; 
          }
        }
        j=i; 
      }
      return inPoly; 
    }

    With the parameters of the function being given as such :

    //polygon coordinates
      var points = new Array(new VELatLong(43.64486433588385, -79.3791389465332),
      new VELatLong(43.64508171979899, -79.3930435180664),
      new VELatLong(43.63682057801007, -79.38437461853027),
      new VELatLong(43.63946054004705, -79.36819553375244),
      new VELatLong(43.652720712083266, -79.37201499938965),
      new VELatLong(43.65793702655821, -79.39111232757568),
      new VELatLong(43.64927396999741, -79.37222957611084),
      new VELatLong(43.64486433588385, -79.3791389465332));
    
      for(var i=0; i < dataLayer.GetShapeCount(); i++)
      {
        var shape = dataLayer.GetShapeByIndex(i);
        var latlong = shape.GetPoints()[0];
        var lat = latlong.Latitude;
        var lon = latlong.Longitude;
    
        if(pointInPolygon(points,lat,lon))
        {
          shape.Show();
        }
      }
    
      drawPolygon(points);
    }

    The issue is that I do not really know where I can add the points coming from the database into the pointInPolygon function inorder to know if my location lies within the polygon or not. 

    If my point lies within the polygon, I'll like to display a pushpin on the map indicating the location and if not send a message to the user saying the point is not found within those boundaries.

    Please, please, kindly help me. I am still a newbie at programming.

    Thanks in advance!


    Code is passion!




    • Edited by nicekloe Saturday, February 16, 2019 12:37 PM
    Saturday, February 16, 2019 12:31 PM
  • Hi nicekloe,

    Take a look at http://bingmapsv8samples.azurewebsites.net/#Select%20Pushpins%20within%20an%20Isochrone as it colors the pins inside the polygon a different color than those outside.

    Sincerely,

    IoTGirl

    Sunday, February 17, 2019 9:19 PM
    Owner
  • Thanks for responding IoTGirl

    I looked at the Isochrone search example found on the link given above.

    The only issue is that I do not really see how this example solves my problem, since I'll like a user to draw a shape on the map then I perform a search for a location in this shape and display pushpins for locations which are within the map and nothing for locations which aren't included.

    With the Isochrone search example, I do not have the possibility to draw a shape on the map or to perform a search either. 


    Code is passion!

    Monday, February 18, 2019 8:38 AM
  • Hi nicekloe,

    THe isochrone is just a complex polygon.  The exercise to determine which points are inside versus outside should be the same.

    Sincerely,

    IoTGirl

    Tuesday, February 19, 2019 2:39 AM
    Owner
  • Hi IoTGirl

    I could adjust my code for the purpose I'll like to achieve. 

    This is what I have actually

    <script type='text/javascript'>
        var map, drawingManager;
    
        function GetMap() {
            map = new Microsoft.Maps.Map('#myMap', {});
    
            //Load the DrawingTools module
            Microsoft.Maps.loadModule('Microsoft.Maps.DrawingTools', function () {
                //Create an instance of the DrawingTools class and bind it to the map.
                var tools = new Microsoft.Maps.DrawingTools(map);
                //Show the drawing toolbar and enable editing on the map.
                tools.showDrawingManager(function (manager) {
                    //Store a reference to the drawing manager as it will be useful later.
                    drawingManager = manager;
                    //Create a shortcut to the DrawingBarAction to minimize code.
                    var da = Microsoft.Maps.DrawingTools.DrawingBarAction;
                    //Limit which tools appear in the drawing toolbar.
                    manager.setOptions({
                        drawingBarActions: da.polyline | da.polygon | da.erase,
                        fillColor: 'rgba(255, 0, 0, 0.5)'
                    });
                });
            });
        }
    
        function getShapes() {
            //var shapes = manager.getPrimitives();
            var shapes = drawingManager.getPrimitives();
            if (shapes && shapes.length > 0) {
                alert('Retrieved ' + shapes.length + ' from the drawing manager.');
    
                //Get the locations of the polyline/polygon.
                var points = [];
                for (i = 0; i < shapes.length; i++) {
                    points.push(shapes[i].getLocations());          
                    alert(points[i]);
    
                    var lat = 4.1546;
                    var lon = 9.23662;
                    //var latitudes = [];
                    //var longitudes = [];
                    //latitudes.push(points[i].latitudes);
                    //longitudes.push(points[i].longitudes);
                    //alert(latitudes);
                    //alert(longitudes);
                }
    
                if (pointInPolygon(points, lat, lon)) {
                    alert("Point is inside polygon");
                    ////Create custom Pushpin
                    //var pin = new Microsoft.Maps.Pushpin(center, {
                    //    title: 'Microsoft',
                    //    subTitle: 'Here',
                    //    text: '1'
    
                    //    //Add the pushpin to the map
                    //    map.entities.push(pin);
                }
                else {
                    alert("Point is not found in polygon");
                }
                
                //return locations;
            }
            else {
                alert('No shapes in the drawing manager.');
            }
        }
    
        function pointInPolygon(points, lat, lon) {
            var i;
            var j = points.length - 1;
            var inPoly = false;
    
            for (i = 0; i < points.length; i++) {
                if (points[i].Longitude < lon && points[j].Longitude >= lon || points[j].Longitude < lon && points[i].Longitude >= lon) {
                    if (points[i].Latitude + (lon - points[i].Longitude) / (points[j].Longitude - points[i].Longitude) * (points[j].Latitude - points[i].Latitude) < lat) {
                        inPoly = !inPoly;
                    }
                }
                j = i;
            }
            return inPoly;
        }
    
    </script>
    <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[Bing Map Key]' async defer></script>
    
    
    <div class="row">
        <div class="col-lg-12">
            <div id="myMap" style=";width:950px;height:600px;"></div>
            <input type="button" class="btn btn-primary" value="Get Shapes" onclick="getShapes()" />
        </div>
    </div>

    I tried taking the latitude and longitude coordinates of a point from a bing map to test the algorithm. I drew a polygon on the map containing the location of which I had earlier retrieved the coordinates. Logically the result should be that the location(point) is within the polygon.

    But when I executed the code, I have the opposite message displayed : "Point is not found in polygon".

    I do not know where I'm going wrong. Please, any help?


    Code is passion!

    Wednesday, February 20, 2019 3:53 PM
  • For your purpose you can use intersects or intersection methods which are geometry calculations of Spatial Math Module, see here: https://docs.microsoft.com/en-us/bingmaps/v8-web-control/modules/spatial-math-module/geometry-calculations.

    See also this code sample: http://bingmapsv8samples.azurewebsites.net/#Select%20Data%20in%20Drawn%20Polygon%20Area
    As noted: it shows how to use the drawing tools to draw a polygon search area on the map and then search for all shapes on the map that are within that polygon.
    And that seems to be exactly what you want to achieve.

    Wednesday, February 20, 2019 7:28 PM
    Moderator
  • Thanks for your answer S1mon

    But the intersection methods of the Spatial Math module "Returns an object that represents the area where two shapes intersect. 

    In my case, I do not have two shapes on the map. I only have the polygon as a shape and it is inside this polygon that I am performing a search. 


    Code is passion!

    Thursday, February 21, 2019 9:54 AM
  • Intersection is actually used in sample code that I shared link for, have you looked into that example?
    Still you can check other method that I mentioned: intersects - Determines if two shapes intersect or not.

    It looks like code that you’re trying to use was written for old v6.3 map control:
    http://msdn.microsoft.com/en-us/library/cc451895.aspx#polygon-search
    when there was no Spatial Math functionality. Have you tried to debug it? Does it return any value for example for points[i].Longitude? Check points array, this is an array within array, if you still want to use this code you could add below in the first line under your pointInPolygon function:
    points = points[0].slice()
    And also make sure to change all Longitude and Latitude to longitude and latitude.
    However I would advise to use Spatial Math module instead.

    • Proposed as answer by S1mon_Moderator Thursday, February 21, 2019 4:59 PM
    • Edited by S1mon_Moderator Thursday, February 21, 2019 5:02 PM
    • Marked as answer by nicekloe Tuesday, February 26, 2019 7:43 AM
    Thursday, February 21, 2019 4:59 PM
    Moderator
  • Hi S1mon, please assist I am in need of a solution that might be related to this.

    my question is: Does the below function return locations(markers) inside the polygon or the points that construct the polygon?

    var locations=[];
    for (i=0; i<shapes.length; i++){
     locations.push(shapes[i].getLocations())
    }

    Thanks

    Thursday, September 19, 2019 8:11 AM
  • Hi Abel,

    This is in S1mon_'s original answer above posted with the code you reference:

    As noted in documentationgetPrimitives() - Gets an array of shapes that are in the layer. This can be used to iterate over the individual shapes.

    Sincerely,

    IoTGirl


    Thursday, September 19, 2019 4:29 PM
    Owner