【问题标题】:Shading a map according to data for a set of coordinates根据一组坐标的数据对地图进行着色
【发布时间】:2018-02-07 19:16:58
【问题描述】:

我有一组 1000 个坐标,每个坐标代表一个特定州的城市中心。这些镇属于 20 个县之一,我知道哪些镇属于哪个县。我希望根据每个县的数据对地图进行着色。例如,如果一个县的值为 100%,那么我希望将该县涂成深红色,如果一个县与 0% 相关联,那么我会将这部分地图涂成白色。

我没有每个县的边界,因为这些都是旧县,从旧地图中追踪边界需要大量工作。我有国家的边界​​,包括岛屿和湖泊等。

所以这是我拥有的数据:

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 

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

以及州界。

解决方案1:因此,创建所需地图的一种方法可能是在每个坐标(城镇)周围创建多边形,该多边形代表地图上最靠近该城镇的所有区域,并且不靠近其他城镇。然后我根据它所在县的数据为这个多边形着色。

解决方案 2:也许更好的方法是在城镇之间混合颜色。因此,如果我在不同的县有两个相邻的城镇,一个是 100%,一个是 0%,那么它们之间的中间点将是粉红色(深红色和白色之间的中间点)。

因此,我希望以图像文件的形式以编程方式生成此地图,该文件易于扩展,并且我可以将其导入到 Photoshop 之类的软件中以添加其他元素。在这种情况下你会推荐 SVG 吗?

我可以使用什么库或算法来生成解决方案 1 中要求的多边形?

是否有一个库可用于生成具有解决方案 2 要求的渐变网格的 SVG 文档?

如果可能,我希望使用 Python3,但我对其他语言持开放态度。我也对 SVG 的其他解决方案和替代方案持开放态度。

我正在使用 MacOS。

【问题讨论】:

标签: python macos svg geometry geospatial


【解决方案1】:

您的第一种方法称为 Voronoi 图表

wikipedia中的描述

有一种使用 javascipt 的 D3 库的这种图表的解决方案

D3 approach

为了完善这个解决方案,我在此处粘贴了 M.Bostock 示例中的代码

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

您的第二个解决方案可以通过 OpenGL 和 Gouraud 着色轻松实现,但是将其导出为 SVG(或位图以外的任何其他内容)并不容易。我会考虑任何替代方案。

【讨论】:

【解决方案2】:

对于python中的解决方案1,您可以在scipy中使用Voronoi Diagrams。以下代码(此SO post 的修改版本)创建了一个voronoi 图,根据每个国家的值使用不同的alpha 绘制它并将其保存到图像Map.png

import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
import random

# make up data points
points = np.random.rand(15,2)
values = np.random.uniform(low=0.0, high=1.0, size=(len(points),))

# compute Voronoi tesselation
vor = Voronoi(points)

# plot
voronoi_plot_2d(vor)

# colorize
for region, value in zip(vor.regions, values):
    if not -1 in region:
        polygon = [vor.vertices[i] for i in region]
        plt.fill(*zip(*polygon), color='r',  alpha=value)

plt.savefig('Map.png')

您的积分应加载到第 7 行的 points 变量中,国家的百分比加载到第 8 行的 values 变量中。

【讨论】:

    【解决方案3】:

    虽然有用于通用数据表示的强大框架,但适合此特定任务的工具是 GIS。我将尝试解释如何在 QGIS 中执行此操作。

    1. 准备数据以导入 QGIS。

    使用以下格式的数据创建一个 CSV 文件:

    Town,X,Y,County,Value
    Town1,50.1,4.89,County1,100
    Town2,49.9,4.78,County1,100
    Town3,50.3,4.59,County1,100
    Town4,50.2,4.99,County1,100
    Town5,50.0,4.99,County1,100
    ...
    Town1000,57.0,8.33,County20,0
    
    1. 将其添加为 CSV(分隔文本)层

      • 图层 -> 添加图层 -> 添加分隔文本图层
    2. 自定义创建图层的样式以获得您在第二个变体中描述的热图。

      • 在图层面板(左下角)右击图层标题->属性->符号系统
      • 将“单个符号”下拉菜单更改为“热图”
      • 点击“应用”
      • 在“Weight points by”中选择“Value”字段(记得在 CSV 中吗?)
      • “申请”
      • 根据您的需要调整其他参数(色带、半径)
    3. 从此层创建一个 Voronoi 多边形

      • 矢量 -> 几何工具 -> Voronoi 多边形
      • 点击目标图层路径输入框附近的“…”,选择“保存到文件”,保存到GeoJSON图层(QGIS不支持CSV中的多边形图层,如果你理解可以选择其他格式)。李>
      • 点击“在后台运行”。
    4. 自定义新建图层的样式,让每个县的区域用不同的颜色着色。

      • 在图层面板(左下角)右击图层标题->属性->符号系统
      • 选择“分类”而不是“单个符号”
      • 在“列”下拉菜单中选择“县”
      • 点击“分类”为所有县分配颜色
      • “申请”
    5. 从当前地图创建 SVG:

      • 项目 -> 新打印布局

      • 点击工具面板上的“添加新地图到布局”按钮,绘制地图的大矩形放置到布局上。

      • 点击“导出为 SVG”

    就是这样。

    Voronoi 多边形上的黑色到透明热图 - https://svgshare.com/s/5MZ

    仅热图 - https://svgshare.com/s/5ND

    我用来生成数据的脚本 - https://gist.github.com/ei-grad/1355223cd8a3c6ba16deb454ddef50b4

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-06
      • 2012-08-06
      • 2014-04-03
      • 2021-09-03
      • 2021-10-01
      • 2020-05-17
      • 2018-10-04
      • 2014-11-25
      相关资源
      最近更新 更多