none
Bing Maps V8 overlay GeoJSON not working

    Question

  • Hi,

    I have a function that's using D3.js to extract the coordinates from GeoJSON files.  I then use Microsoft's GeoJson module to parse them into Bing shapes.  Then I added the shapes to a layer and added the layer to Bing Map.  Why aren't they showing?  There are multiple shapes in a GeoJson file.  Following are my code snippet:

    function loadGeoJsonLayer(stname, fips) {       
            var vCenter = getStateCenter(stname);
            var map = new Microsoft.Maps.Map("#divMap", {});
            var st = getStAbbr(stname);
            var geoShps;
            var jsonShps;
            var coords;
            var shapes;
            var layer;
    
            //Load the drawing toolbar to the new map instance
            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 in the map
                tools.showDrawingManager(function (manager) {
                    //store a reference to the drawing manager as it will be used later
                    drawingManager = manager;
                });
            });
    
            //Change the map view
            map.setView({
                mapTypeId: Microsoft.Maps.MapTypeId.aerial,
                center: new Microsoft.Maps.Location(vCenter[0], vCenter[1]),  //order: latitude, longitude
                zoom: 10
            });
    
            d3.json("/data/geo/" + st + "/" + fips + ".json", function (error, data) {
                if (error) throw error;
    
                geoShps = data.features;
                jsonShps = new Array(geoShps.length);
                coords = new Array(geoShps.length);
    
                for (var i = 0; i < geoShps.length; i++) {
                    //get coordinates
                    coords[i] = [geoShps[i].properties.Latitude, geoShps[i].properties.Longitude];
                    jsonShps[i] = { "type": "Polygon", "coordinates": [[coords[i]]] };
                }
    
                //Load the GeoJson module
                Microsoft.Maps.loadModule("Microsoft.Maps.GeoJson", function () {
                    shapes = Microsoft.Maps.GeoJson.read(jsonShps, {
                        polygonOptions: {
                            fillColor: "rgba(255,0,0, 0.5)",
                            strokeColor: "orange",
                            strokeThickness: 5
                        }
                    });
    
                    //Create a layer to hold the shapes
                    layer = new Microsoft.Maps.Layer();
    
                    //Add the shapes to layer
                    layer.add(shapes);
                    layer.setVisible(true);
    
                    //Add layer to map
                    map.layers.insert(layer);
                });
            });
        }

    Users of the website are supposed to select a state from a dropdownlist.  Then select a county from another dropdownlist. Then my function above is supposed to run.  There is no error resulting from the function.  So I can't figure out why the shapes are not showing on the map.

    I'd appreciate any help.


    Marilyn Gambone

    Monday, April 1, 2019 2:20 PM

Answers

  • Final Update:  4/19/2019

    Figured out what was wrong.  There are some features whose geometries have null values.  I deleted these from my GeoJson files, and now the features load without any memory problem.

    What a task.  This is it I hope.  Seems to be working so far!


    Marilyn Gambone

    • Marked as answer by deskcheck1 Friday, April 19, 2019 3:39 PM
    Friday, April 19, 2019 3:39 PM

All replies

  • Hi Marilyn,

    Have you taken a look at the samples at https://www.bing.com/api/maps/sdk/mapcontrol/isdk/geojsonwritetogeojson?

    Click through the menu on the left to see more ways to ingest the data.  Note:  Have you debugged you file to be valid GeoJSON?

    Sincerely,

    IoTGirl

    Monday, April 1, 2019 3:27 PM
    Owner
  • Hi,

    I've looked over most of the codes in that website.  I haven't found anything that helps me render the multiple polygons in my geojson data.

    I tried using a CustomOverlay module found here.  But even with this simple sample, I couldn't duplicate it to render the circles.

    I know the geojson shapes are okay since I could see them when I debug the web app using Google's browser.  I've also made sure they are all in EPSG:3857 (or whatever is the Web Mercator Auxiliary Sphere projection is).  All the geojson object has CRS properties.  So it can't be the geojson file.

    I don't understand why I'm adding the geojson objects to the layer but the layer is not rendering on the map.  BTW, I've updated the codes above to modify the reading of geojson shapes.

    I still have no luck.  Frankly, doing this using Google map is so much easier.  I simply create an OverlayView and add it and it shows right away.  But I'm kind of partial to Microsoft products, so I'm really trying to make this work.  I'm running out of time and I hate to switch over to using Google maps in the interest of time.

    I do hope Bing Maps provide more samples using actual GeoJson data that most GIS professionals use (e.g., actual shapefiles for US counties).


    Marilyn Gambone

    Wednesday, April 3, 2019 1:08 AM
  • Hi Marilyn,

    We do have the counties in our SDS service. Our sample shows Zip codes https://www.bing.com/api/maps/sdk/mapcontrol/isdk/sdsloadmultipleboundaries but there are other entity types available (https://docs.microsoft.com/en-us/bingmaps/v8-web-control/map-control-concepts/spatial-data-services-module-examples/geodata-api/search-boundary-example has the entity options called out

    We also have the following Census generated solution https://social.msdn.microsoft.com/Forums/en-US/15f3a443-ed3e-494f-83c1-cb8739989d31/count-of-shape-provide-by-using-census-data-is-proper-or-not?forum=bingmapsajax

    I think you may need to just do the setview *after* you post the layer.  I suspect the layer is being added but not "pushed" or refreshed so not getting updated/rendered.  I will dig through some of my old code because I think I ran into something similar when I wanted to put a truck and car route on one map.

    Sincerely,

    IoTGirl

    Wednesday, April 3, 2019 3:46 AM
    Owner
  • PS If I take https://www.bing.com/api/maps/sdk/mapcontrol/isdk/sdsloadboundaryfromsearch#JS

    And change "New York City" to "King" and PopulatedPlace" to "AdminDivision2" it does show King County Washington.

    Here is the code:

    ar map = new Microsoft.Maps.Map(document.getElementById('myMap'), {});
    //Load the Bing Spatial Data Services module
    Microsoft.Maps.loadModule(['Microsoft.Maps.SpatialDataService', 'Microsoft.Maps.Search'], function () {
        var searchManager = new Microsoft.Maps.Search.SearchManager(map);
        var geocodeRequest = {
            where: 'King',
            callback: function (geocodeResult) {
                if (geocodeResult && geocodeResult.results && geocodeResult.results.length > 0) {
                    map.setView({ bounds: geocodeResult.results[0].bestView });
                    var geoDataRequestOptions = {
                        entityType: 'AdminDivision2',
                        getAllPolygons: true
                    };
                    //Use the GeoData API manager to get the boundary of New York City
                    Microsoft.Maps.SpatialDataService.GeoDataAPIManager.getBoundary(geocodeResult.results[0].location, geoDataRequestOptions, map, function (data) {
                        if (data.results && data.results.length > 0) {
                            map.entities.push(data.results[0].Polygons);
                        }
                    }, null, function errCallback(networkStatus, statusMessage) {
                        console.log(networkStatus);
                        console.log(statusMessage);
                    });
                }
            },
        };
        searchManager.geocode(geocodeRequest);
    });
    

    Wednesday, April 3, 2019 3:53 AM
    Owner
  • Hi,

    I'm not sure I can use the SpatialDataService.  I don't really need the county boundary.  I need the boundaries of farms within a county.  The result should be similar to this:

    So, I need to be able to upload the farms within each county.  The one above is New Castle, Delaware.  Then I'd need to be able to hover or click each farm polygon to show its properties in an info window.

    I'm hoping I'd just add these farms to a layer and then add the layer to the map and it should show the boundaries of the farms/polygons.

    The farms are proprietary shapefiles which we generated in-house.

    Here's another view of my data using erams.com website.  I overlaid it into a Bing Map base layer:


    Marilyn Gambone



    • Edited by deskcheck1 Wednesday, April 3, 2019 4:51 PM
    Wednesday, April 3, 2019 4:18 PM
  • UPDATE: 4/4/2019:

    I found some errors on my GeoJSON data. I'm working on fixing these first.  I'll let you know my progress once I've reconciled these...could be a while :)


    Marilyn Gambone

    Friday, April 5, 2019 12:30 AM
  • Great Marilyn!  Please do let us know as we are happy to help.
    Friday, April 5, 2019 8:43 PM
    Owner
  • Okay,

    I modified my GeoJSON data.  Before, it was only showing a pair of coordinates, instead of an array of coordinates. I've got it to reflect those coordinate arrays for each shape.  The code now looks like this:

    function loadGeoJsonLayer(stname, fips) {     
            var vCenter = getStateCenter(stname);
            var st = getStAbbr(stname);        
    
            map = new Microsoft.Maps.Map("#divMap", {
                mapTypeId: Microsoft.Maps.MapTypeId.aerial,
                center: new Microsoft.Maps.Location(vCenter[0], vCenter[1])
            });
    
            //Load Microsoft Drawing tool
            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 in the map
                tools.showDrawingManager(function (manager) {
                    //store a reference to the drawing manager as it will be used later
                    drawingManager = manager;
                });
            });
    
            d3.json("/data/geo/" + st + "/" + fips + ".json", function (error, data) {
                if (error) throw error;
    
                geoShps = data.features;
                layer = new Microsoft.Maps.Layer();
                var bmArray = new Array();
    
                //Process raw geojson data for Bing Maps: order to lat/lng
                for (var i = 0; i < geoShps.length; i++) {
                    var len = geoShps[i].geometry.coordinates[0].length;
                    var jsonShps = new Array(len);                
    
                    for (var j = 0; j < len; j++) {
                        jsonShps[j] = { "type": "Polygon", "coordinates": [geoShps[j].geometry.coordinates[0][0][1], geoShps[j].geometry.coordinates[0][0][0]] };                    
                    }
    
                    bmArray.push(jsonShps);
                }
                
                //Remove any existing data from the map
                map.entities.clear();
                shapes = new Array(bmArray.length);
    
                //Load Microsoft's GeoJson module
                Microsoft.Maps.loadModule("Microsoft.Maps.GeoJson", function () {
                    //Parse the GeoJson object into a Bing Maps shape.
                    for (var n = 0; n < bmArray.length; n++) {
                        shapes[n] = Microsoft.Maps.GeoJson.read(bmArray[n], {   //lat/lng for Bing map
                            polygonOptions: {
                                fillColor: "rgba(0,0,255, 0.5)",
                                strokeColor: "orange",
                                strokeThickness: 1
                            }                        
                        });
                        map.entities.push(shapes[n]);
                    }
    
                    //Calculate the bounding box of the data
                    var databounds = Microsoft.Maps.LocationRect.fromShapes(shapes);
    
                    //Update the map view to show the data
                    map.setView({ bounds: databounds, padding: 50 });
                });
            });
        }
    

    I get an error "Cannot read property of "toLowerCase of undefined" at function.n._parse...

    Still don't know what I'm doing wrong.

    Appreciate more help. :)


    Marilyn Gambone

    Monday, April 8, 2019 9:12 PM
  • Hi Marilyn,

    There are quite a few references on the internet for that error and it often seems related to mis-matched brackets.  It is not specific for maps, the call is https://www.w3schools.com/jsref/jsref_tolowercase.asp

    Sincerely,

    IoTGirl


    Tuesday, April 9, 2019 5:52 AM
    Owner
  • Hi IotGirl,

    Thanks.  I will research this further then and let you know if I ever solve this mystery :)


    Marilyn Gambone

    Tuesday, April 9, 2019 12:31 PM
  • Excellent. Please don't hesitate to let us know.
    Tuesday, April 9, 2019 10:43 PM
    Owner
  • Hi,

    Turns out, I found a bigger problem:  the GIS data they gave me was in a WRONG projection.  It's in some custom projection that doesn't match/align with "standard" WGS 1984 World Mercator projection.  So no matter what I do, I'm getting the wrong latitudes and longitudes.  So, I sent it back for our staff to make the corrections first.  Will update you when I get the correct data--hopefully :)


    Marilyn Gambone

    Wednesday, April 10, 2019 2:12 PM
  • Wow!  That would have been tough to catch!  Please do keep in touch!
    Wednesday, April 10, 2019 6:04 PM
    Owner
  • Hi,

    UPDATE:  Our data now has the correct Geographic Coordinate System. The original data came from NOAA and was in .bil format.  So we had to convert them into ESRI Grid format in order to re-define its spatial reference.  The .bil format had meters in its units instead of latitude/longitude.

    So now that that's out of the way, I used the library D3.js to "re-arrange" the GeoJson format from [longitude, latitude] to Bing Maps format of [latitude, longitude].  I got that out of the way, too.

    Now, my latest revised function in JavaScript to overlay the farm features/polygons is as follows:

    function loadGeoJsonLayer(stname) {
        var vCenter = getStateCenter(stname);
        var st = getStAbbr(stname);
        var county = $("#fcountyDdl").val();
        var chkWs = hasWhiteSpace(county);
    
        //Get rid of whitespaces in county name
        county = chkWs === true ? county.replace(' ', '') : county;
    
        map = new Microsoft.Maps.Map("#divMap", {
            mapTypeId: Microsoft.Maps.MapTypeId.aerial,
            center: new Microsoft.Maps.Location(vCenter[0], vCenter[1])
        });
    
        //Load Microsoft Drawing tool
        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 in the map
            tools.showDrawingManager(function (manager) {
                //store a reference to the drawing manager as it will be used later
                drawingManager = manager;
            });
        });
    
        var geoFile = "/data/geo/" + st + "/" + county + ".json";
    
        d3.json(geoFile, function (error, data) {
            if (error) throw error;
    
            geoShps = data.features;
            bmArray = new Array();
    
            //Process raw geojson data: re-order coordinates to lat/lng for Bing Maps
            for (var i = 0; i < geoShps.length; i++) {
                var len = geoShps[i].geometry.coordinates[0].length;
                var jsonShps = new Array(len);
    
                for (var j = 0; j < len; j++) {
                    jsonShps[j] = { "type": "Polygon", "coordinates": [geoShps[j].geometry.coordinates[0][0][1], geoShps[j].geometry.coordinates[0][0][0]] };
                }
    
                bmArray.push(jsonShps);
            }
    
            var shapes = new Array();        
    
            //Load GeoJson Module
            Microsoft.Maps.loadModule("Microsoft.Maps.GeoJson", function () {
                for (var n = 0; n < bmArray.length; n++) {
                    shapes[n] = Microsoft.Maps.GeoJson.read(bmArray[n], {
                        polygonOptions: {
                            fillColor: "rgba(0,255,255, 0.3)",
                            strokeColor: "orange",
                            strokeThickness: 1
                        }
                    });
    
                    map.entities.push(shapes[n]);
                }
            });
        });
    }


    I am trying to base this from code sample I found here.  But my code doesn't load the Microsoft GeoJson Module.  It skips it but doesn't display any error either.

    A sample GeoJson file I have is as follows (just showing a few features):

     [0] [
        [0] {type: "Polygon", coordinates: [39.83608894300386, -75.54981716860517]},
        [1] {type: "Polygon", coordinates: [39.83354360135618, -75.55489667634049]},
        [2] {type: "Polygon", coordinates: [39.82805252080726, -75.54489722152957]},
        [3] {type: "Polygon", coordinates: [39.83164680525591, -75.55834047813053]},
        [4] {type: "Polygon", coordinates:[39.834469668340525, -75.57707558307166]} ],
    [1] [
    	[0] {type: "Polygon", coordinates: [39.83608894300386, -75.54981716860517]},
    	[1] {type: "Polygon", coordinates: [39.83354360135618, -75.55489667634049]},
    	[2] {type: "Polygon", coordinates: [39.82805252080726, -75.54489722152957]},
    	[3] {type: "Polygon", coordinates: [39.83164680525591, -75.55834047813053]}
    ]

    I wonder if anyone can help me with this.  I'd appreciate it very much.

    BTW, these farms should be somewhere in Delaware.


    Marilyn Gambone



    • Edited by deskcheck1 Monday, April 15, 2019 4:10 PM
    Monday, April 15, 2019 4:02 PM
  • Update:  4-19-2019

    Found out 2 things:

    1.  I don't have to RE-ORDER GeoJson file's [longitude, latitude] format.  Leave them be 'cause Microsoft GeoJson Module knows how to read them as is.

    2.  I'm running out of memory when I load thousands of polygons per county.  I experimented on including just a few polygons in my GeoJson data, and the shapes overlayed on Bing Map easily.  I don't know why the website eRams has no problem loading thousands of shapefiles at the same time.

    Why am I able to overlay ESRI's shapefiles on Bing Map in eRams' website?  Is there a Bing Map module for loading shapefiles instead of GeoJson?  It seems that shapefiles use less memory than GeoJson.

    BTW, with the above findings, my function to overlay the GeoJson file has been simplified as follows:

    function loadGeoJsonLayer(stname) {
        var vCenter = getStateCenter(stname);
    
        map = new Microsoft.Maps.Map("#divMap", {
            mapTypeId: Microsoft.Maps.MapTypeId.aerial,
            center: new Microsoft.Maps.Location(vCenter[0], vCenter[1]),
            zoom: 10
        });
    
        Microsoft.Maps.loadModule('Microsoft.Maps.GeoJson', function () {
            var featureCollection = Microsoft.Maps.GeoJson.read(getNewCastle(), { polygonOptions: { fillColor: 'rgba(0, 255, 255, 0.3)' } });
            map.entities.push(featureCollection[i]);
        });
    }
    Problem now is the sample function, "getNewCastle()".  It's a test to overlay only a few features.  I can't load the entire feature collection since I run out of memory, although, it doesn't flag as error.  It just doesn't do anything on the map.  Whew!  Need to look for another way.



    Marilyn Gambone


    • Edited by deskcheck1 Friday, April 19, 2019 3:28 PM
    Friday, April 19, 2019 2:27 PM
  • Final Update:  4/19/2019

    Figured out what was wrong.  There are some features whose geometries have null values.  I deleted these from my GeoJson files, and now the features load without any memory problem.

    What a task.  This is it I hope.  Seems to be working so far!


    Marilyn Gambone

    • Marked as answer by deskcheck1 Friday, April 19, 2019 3:39 PM
    Friday, April 19, 2019 3:39 PM
  • That is great news! Congrats on the breakthrough!
    Saturday, April 20, 2019 12:04 AM
    Owner