2

I would like to create a dot density map using Google Maps. I have all the counties of my state outlined, along with their corresponding populations. I want to know how I could place a number of dots randomly within each county to represent the population of that county. We want to make a dot density map instead of a choropleth map because we like the representation better, but I can't figure out how to distribute dots among a polygon outline.

This is a poor example of sort of what I'm looking to make.

Community
  • 1
  • 1
philthyfool
  • 194
  • 2
  • 5
  • 17

2 Answers2

0

Well, I've come to a very inefficient yet suitable solution to my problem. In case anybody would either like to help me improve my method or use it themselves, this is what I did.

I used this answer as a guide to test whether or not a point would fall in a particular polygon. As I create the polygons that outline the border of counties in my state, I add each latitude to one array, and each longitude to another. I then determine min and max values for each array as a bounding box that a point would have to be in in order to fall within the county lines. I then pick random numbers between those mins and maxes and test whether they fall within the county. If they do, I add a marker there. I do those within a loop that counts how many markers are added until it is proportional to the population of that particular county. Here is the code:

function addMarkers() {
            var loc = "Resources/CaliforniaCounties.json";

            $.getJSON(loc, function (data) {
                $.each(data.features, function (key, val) {

                    var xArray = []; //
                    var yArray = []; //

                    var coords = [];
                    var latlng;
                    var bounds = new google.maps.LatLngBounds();
                    var polygon;

                    $.each(val.geometry.coordinates[0], function (i, item) {
                        latlng = new google.maps.LatLng(item[1], item[0]);
                        xArray.push(item[0]); //
                        yArray.push(item[1]); //
                        coords.push(latlng);
                        bounds.extend(latlng);
                    });

                    var nverts = xArray.length; //
                    var maxX = Math.max.apply(null, xArray);  //
                    var maxY = Math.max.apply(null, yArray);  //
                    var minX = Math.min.apply(null, xArray);  //
                    var minY = Math.min.apply(null, yArray);  //


                    polygon = new google.maps.Polygon({
                        paths: coords,
                        strokeColor: "#000000",
                        strokeOpacity: 1,
                        strokeWeight: 01,
                        fillColor: "#cccccc",
                        fillOpacity: .5
                    });

                    polygon.center = bounds.getCenter();
                    addPolygonClickListener(polygon, val);
                    polygon.setMap(map);

                    polygonArray[val.properties.Name] = polygon;


                    var i = 1;
                    while( i < populations[val.properties.Name] / 10000){
                        var testX = Math.random() * (maxX - minX) + minX; //
                        var testY = Math.random() * (maxY - minY) + minY; //

                        if(pnpoly(nverts, xArray, yArray, testX, testY) == 1){  //
                            var mlatlng = new google.maps.LatLng(testY, testX); //
                            var marker = new google.maps.Marker({ position: mlatlng, icon: "Resources/dot.png", map: map });   //
                            i++;
                        }
                    }



                });
            });

        function pnpoly(nvert, vertx, verty, testx, testy)
        {
           var i, j, c = 0;
           for (i = 0, j = nvert-1; i < nvert; j = i++) 
           {
              if ( ((verty[i]>testy) != (verty[j]>testy)) &&
              (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
              {
                 c = !c;
              }
           }
          return c;
        }
Community
  • 1
  • 1
philthyfool
  • 194
  • 2
  • 5
  • 17
0

I have a more efficient way to do this. You can use the same features to create color map, which is second, invisible canvas element. In this, each county is a unique color derived from it's index in the feature list. Using getImageData(), you can get the bit map of the canvas. Then, you can use it to test whether your random, bounding box constrained coordinates fall within the county by checking the color of the colormap at that coordinate. This test is a O(1) operation, where as yours looks like it's O(n).

I am using this technique to create a dot density map of counties in china, and the performance is fine. I started with this guy's code example:

https://gist.github.com/awoodruff/94dc6fc7038eba690f43