Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shading a map according to data for a set of coordinates

I have a set of 1000 coordinates, with each representing the urban centres of a particular state. These towns belong to one of 20 counties and I know which towns belong to which county. I wish to shade a map based on data I have for each county. For example, if a county has a value of 100% then I wish to color this county dark red, if a county is associated with 0% then I will color this part of the map white.

I don't have the boundaries for each county since these are old counties and it would involve a huge amount of work to trace the boundaries from old maps. I have the boundaries of the state including islands and lakes etc.

So here is the data I have:

Town1 50.1,4.89 County1    
Town2 49.9,4.78 County1    
Town3 50.3,4.59 County1    
Town4 50.2,4.99 County1    
Town5 50.0,4.99 County1    
...
Town1000 57.0,8.33 County20 

and

County1 100%   
County2 100%   
County3 68%   
...
County20 0% 

as well as the state boundaries.

Solution1: So, one approach to create my desired map might be to create polygons around each coordinate (town), with this polygon representing all the area on the map closest to this town, and closer to no other town. Then I color this polygon according to the data of its county.

Solution2: Perhaps a better approach would be to blend colors between towns. So if I have two adjacent towns in different counties, one with 100% and one with 0%, then the half way point between them would be coloured pink (half way between dark red and white).

So I wish to programatically produce this map in the form of an image file where this file is easily scalable and where I can import it into the likes of Photoshop in order to add other elements. Would you recommend SVG in this case?

What library or algorithm might I use to produce the polygons as required in Solution 1?

Is there a library I can use to produce an SVG document with a gradient like mesh as required by Solution 2?

I wish to use Python3 if possible but I am open to other languages. I am also open to other solutions and alternatives to SVG.

I am using MacOS.

like image 896
Baz Avatar asked Oct 29 '22 20:10

Baz


1 Answers

Your first approach is called a Voronoi diagramm

See the description in wikipedia

There is a solution for this kind of diagramms using D3 library for javascipt

D3 approach

Just to make this solution complete, I am pasting here the code from M.Bostock example

var w = 1280,
    h = 800;

var projection = d3.geo.azimuthal()
    .mode("equidistant")
    .origin([-98, 38])
    .scale(1400)
    .translate([640, 360]);

var path = d3.geo.path()
    .projection(projection);

var svg = d3.select("body").insert("svg:svg", "h2")
    .attr("width", w)
    .attr("height", h);

var states = svg.append("svg:g")
    .attr("id", "states");

var cells = svg.append("svg:g")
    .attr("id", "cells");

d3.json("us-states.json", function(collection) {
  states.selectAll("path")
      .data(collection.features)
    .enter().append("svg:path")
      .attr("d", path);
});

d3.csv("airports.csv", function(airports) {
  var positions = [];

  airports.forEach(function(airport) {
    positions.push(projection([+airport.longitude, +airport.latitude]));
  });

  // Compute the Voronoi diagram of airports' projected positions.
  var polygons = d3.geom.voronoi(positions);

  var g = cells.selectAll("g")
      .data(airports)
    .enter().append("svg:g");

  g.append("svg:path")
      .attr("class", "cell")
      .attr("d", function(d, i) { return "M" + polygons[i].join("L") + "Z"; })
      .on("mouseover", function(d, i) {
        d3.select("#footer span").text(d.name);
        d3.select("#footer .hint").text(d.city + ", " + d.state);
      });

  g.append("svg:circle")
      .attr("cx", function(d, i) { return positions[i][0]; })
      .attr("cy", function(d, i) { return positions[i][1]; })
      .attr("r", 1.5);
});

Your second solution is easily achievable with OpenGL and Gouraud shading, but then it's not easy to export it to SVG (or to anything else beyond a bitmap). I will think about any alternative to it.

like image 143
vals Avatar answered Nov 15 '22 06:11

vals