Generate a dot density map with the help of Google Maps

I am looking to create a dot density map using Google Maps for my state. I have all the counties outlined with their respective populations, and I want to scatter dots randomly within each county to represent the population. The goal is to make a dot density map rather than a choropleth map because we find that representation more visually appealing. However, I'm struggling to figure out how to distribute the dots within a polygon outline.

Here is a rough example of what I am aiming to achieve.

Answer №1

After much trial and error, I have devised a somewhat inefficient but workable solution to tackle my issue. If anyone is interested in enhancing this method or using it for their own purposes, feel free to take a look at what I've come up with.

My approach involves leveraging this helpful answer as a foundation to determine if a point falls within a specific polygon. While mapping out the county borders in my state, I organize latitude values into one array and longitudes into another. By establishing minimum and maximum values for each array, defining a bounding box that encapsulates where a point must reside to be considered within county lines, I then generate random numbers within those bounds and test their inclusion in the county. If successful, I place a marker there. This process is repeated within a loop that iterates until the number of markers added aligns with the population density of the respective county. Below is the code snippet featuring my implementation:

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;
        }

Answer №2

I have discovered a more effective method for accomplishing this task. By utilizing the same functionalities, you can create a color map as a second hidden canvas element. Each county will be assigned a unique color based on its position in the feature list. Utilizing getImageData() allows you to extract the bitmap of the canvas, which can then be used to determine if randomly generated coordinates within a bounding box fall within a specific county by examining the color of the colormap at that particular coordinate. This operation is performed in constant time (O(1)), while the previous method appears to be linear (O(n)).

I have successfully implemented this technique to generate a dot density map of counties in China, and the performance is satisfactory. My initial inspiration came from the following code example:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

minimize the size of the image within a popup window

I encountered an issue with the react-popup component I am using. When I add an image to the popup, it stretches to full width and length. How can I resize the image? export default () => ( <Popup trigger={<Button className="button" ...

Leveraging AngularJS html5mode in conjunction with express.js

Client-side: when("/page/:id", { templateUrl: "partials/note-tpl.html", controller : "AppPageController" }); $locationProvider.html5Mode( true ); Html: <a ng-href="/page/{{Page._id}}">{{Page.name}}</a> Server-side: app.use("/pag ...

Utilize JQuery AJAX to retrieve a PHP array and then store it in a JavaScript variable

I am facing a challenge that seems simple to resolve, but it's proving to be quite tricky. Currently, I have a functional PHP file that fetches data from a database and stores it in an array. This file does not require any parameters and the output i ...

In JavaScript, when all values are false in an object, the object's value should be set to False

My task involves working with a JSON data object that contains multiple key-value pairs. I need to determine whether at least one value is false and set another variable to "false" accordingly. Here is the JSON data that I am handling: var objectVal = re ...

When running the command "NPM start" in Gulp, you may encounter a situation where a blank page appears with the error message: "Cannot GET /"

I've been following a comprehensive tutorial on setting up a new desktop app using Angular2, Bootstrap, Yeoman, and Gulp. However, I encounter an issue when trying to test the code locally after reaching the frontend task section. Every time I run np ...

AngularJS- issue with button visibility on 'toolbar' widget

In my angularJS application, there is a page with multiple widgets displayed. When a user clicks on the 'Settings' button on the page (separate from the widgets), a toolbar for each widget appears showing different buttons depending on the widget ...

Using $.ajax to fetch a JSON array from a PHP endpoint

Any assistance would be greatly appreciated if I am making a simple mistake somewhere. Associative Array data_form[name] = value; Action $.ajax({ type: "GET", cache: false, url: "../pages/ajax/takeaction.php", data: ...

Populate a select list in real time with dynamically generated options

I'm facing a challenge at the moment; I am using JavaScript to dynamically generate select boxes, however, I require Ajax to populate them with options. At the moment, my code is returning undefined and I am unsure of how to proceed. While my PHP succ ...

Keyboard control of Material UI Checkbox

As we work on developing a web application using react and material ui, accessibility for persons with disabilities is a key consideration. This means ensuring that the web application is operable through keyboard navigation. It's important that user ...

Google Maps autocomplete feature is causing the input to update only after clicking in ng-model

After fetching a Google Maps place ID from a REST API, I utilize the Google Maps API to retrieve the place object in this manner: var geocoder = new google.maps.Geocoder; geocoder.geocode({ 'placeId': data.city }, fun ...

Begin the input box with some text

Currently, I am trying to incorporate a form field that automatically adds "http://" when clicked or typed into by a user. Below is the code snippet I have been using: <script type="text/javascript"> var input = $( "#website" ); input.val( input ...

Attempting to transform a nested JSON document into a CSV format using Powershell

I am facing a challenge converting a nested JSON file into a CSV format using PowerShell. Despite my efforts, I can't seem to figure out the correct logic for it. Here is an example of the content in my JSON file: [ { "Device": ...

Implementing dynamic class bindings with Vue.js using v-for

I am currently using a v-for loop in Vue.js to create a list of items populated with data from an API. Here is an example of the items array: items: [ { foo: 'something', number: 60 }, { foo: 'anything', ...

Obtain a collection of strings from an array of objects based on specified criteria

What is the most efficient method to extract an array of specific strings from an array of objects, where a certain condition needs to be met? Solution Attempt: const array = [{ "Item": "A", "Quantity": 2 ...

Uncomplicating Media Queries in Styled Components with the Power of React.js and Material-UI

My approach to handling media queries in Styled Components involves three distinct functions. One function handles min-width queries, another deals with max-width, and the third caters to both min-width and max-width scenarios. Let me walk you through eac ...

Merging two JSON objects in MULE: A step-by-step guide

I recently delved into MULE and encountered a challenge with combining two JSONs. One is received from an HTTP post request while the other is set as the Payload in a sub flow. I attempted using a custom Transformer without success. Can anyone provide gu ...

Moving data of a row from one table to another in Laravel by triggering a button click

For instance, consider a scenario where clicking a button moves a row to another table in the database and then deletes it. Implementing this functionality in Laravel seems challenging as I am unable to find any relevant resources or guidance on how to pro ...

What is the best way to configure maxSockets in Node.js while working with Express?

Can the maximum number of sockets in Node.js be adjusted while working with the Express framework? More information can be found here. ...

Using AJAX to search through paginated pages is quite simple and effective

Currently, I have developed a JavaScript script that filters names within a list. However, a problem has arisen with pagination - as the list paginates, I am unable to retrieve names without refreshing the page. Is there a way to use AJAX to access and dis ...

What is the best way to separate a table column into a distinct column at the specified delimiter count?

I successfully wrote code that splits the third column into new columns at the slash delimiter. However, I am struggling to modify it to split at the nth (i.e. 2nd) occurrence. I couldn't find a solution online, so I'm reaching out here for help ...