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

Comparison of Web Development Techniques: localStorage versus Cached HTTP

Imagine a scenario where there is a web server responding to a GET request by sending a .json file. The response instructs the browser to cache it for a period of 5 years. Furthermore, picture a webpage that initiates this GET request for the JSON data du ...

Utilize SAPUI5 table control to dynamically display images based on specified conditions

I'm looking to dynamically display an image in a table column based on values from a JSON model. For instance, if the value in the model is greater than 1, I want '1.png' to be displayed in that particular row. The image filename is coming ...

What is the process of reading an excel file in angularjs?

I attempted to read an Excel file by following a tutorial I found at . Unfortunately, I encountered an undefined situation in the highlighted line below while trying to do so in IE11. var reader = new FileReader(); reader.onload = function( ...

Managing Time Before Browser Refresh in AngularLearn how to monitor and examine the time remaining before

In my Angular web application, I am facing an issue where the user's login status is lost every time the browser is refreshed or reloaded. I want to implement a feature that allows the login status to remain active for a short period of time after the ...

Setting a radio button as default based on a variable value can be accomplished by following a few

I am working with 2 radio buttons and I need to dynamically check one based on a variable value. <input type="radio" name="team" id="team_7" value="7"> <input type="radio" name="team" id="team_8" value="8"> The variable number is set dependin ...

Angular generating JSON data

I am trying to figure out how to extract and display the short_title from the JSON object with the "id": 28. I want to use Angular to render this title within an HTML page. { "content": [ { "id": 29, "short_title": "Flow", ...

Conditional statement that includes Node.js scheduling function

I am currently working on a Node.js project and I need to execute a specific portion of conditional code after waiting for five minutes since the last piece of code executed. This action should only happen once, not on a daily basis or any other frequency. ...

Error encountered in Node.js: The listener must be a function

I've been working on adapting the solution provided in (How to create a simple http proxy in node.js?) from HTTP to HTTPS. However, upon attempting to access the proxy through my browser, the server abruptly stops and throws the following error: eve ...

Display and conceal multiple div elements using a timer

Currently, I am working on creating a message box that will display active messages one by one from a MySQL table. The challenge is that the number of divs needed can vary depending on the number of active messages in my database. Using an ajax timer and P ...

What method can be used to incorporate Google Places API into a .js file without using a <script> element?

As I delve into the Google Places API documentation, I noticed that they require the API be loaded in this format: <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script> Is ...

Using VueJS Computed Property along with Lodash Debounce

I have been encountering a slowdown while filtering through a large array of items based on user input. I decided to implement Lodash debounce to address this issue, but unfortunately, it doesn't seem to be having any effect. Below is the HTML search ...

Optimal DynamoDB Configuration for Effective Implementation

Currently, I am developing a save application where users can save articles to their profile. Instead of using a relational database, the application is utilizing DynamoDB. Each article is associated with a specific type: user-id [string][DynamoDBHashKey] ...

"Which is the better choice for a Django application's for loop: views.py or

I'm in the process of creating a Django app that features a word list. The app currently utilizes a speech function to inform the user of the first word on the list. The user is then able to record an audio clip of a word they say, which is converted ...

Unraveling nested JSON elements in Pyspark using the explode function

I'm completely new to working with Spark, and I'm currently attempting to parse a JSON file that contains data to be aggregated. However, navigating through its content has proven to be quite challenging for me. Despite searching for alternative ...

Guide on how to choose a radio button in IONIC with the help of angularJS

<ion-list> <ion-radio ng-model="choice" ng-value="'A'" ng-click='usedGNG("yes")'>Yes</ion-radio> <ion-radio ng-model="choice" ng-value="'B'" ng-click='usedGNG("no")'>No</ion-radio> </ ...

Using a jQuery UI dialog for multiple checkbox selection. The post array cannot be saved for a multi-select until the dialog is opened

CSS <td class="cell"> <a class="opener" id="opener_'.$iterator.'" href="#" rel="#type_dialog_<?= $iterator; ?>">Click here</a> <div id="type_dialog_<?= $iterator; ?>" name="t ...

"What is the best way to ensure that a random array value is printed accurately within an If/Else statement in my Text Adventure

I am currently developing a text-based adventure game where the output in the console log is determined by specific input. The goal is for a message to appear if a goblin inflicts enough attack damage to reduce the player's defense to below 0, stating ...

Ways to restrict the quantity of Firebase compound indexes required for querying with various filters

I'm in the process of developing a Firestore project that includes group chats and forums where users can filter posts based on various criteria: Number of likes Presence of attachments (photos and/or files) 4 Tags (Questions, Exams, Assignments, Not ...

What are the risks of employing conditional rendering in react-router-dom for authentication purposes?

In the following code snippet: If the authentication data sent from the client matches in the backend, a response with the user ID is sent. If setIsAuth sets to true, the Layout Component will display the first case within the Switch component, allowin ...

Tips for speeding up the loading of JSON with large data on HTTP requests or webpages

When requesting the page (via HTTP or webpage), it seems to be very slow and even crashes unless I load my JSON data with fewer entries. This issue is critical as I anticipate needing to work with large amounts of data frequently in the future. Below are t ...