Как сделать мои сюжетные точки гладкими в d3.js с помощью проекции?

Я могу нанести некоторые данные о погоде на карту, используя следующий код. Однако точки представляют собой прямоугольники, и я хотел бы сделать их более гладкими.

Построенные прямоугольники,

Я хотел бы сделать их более плавными, как что-то похожее на Идеальные точки сюжета

Я считаю, что мне нужно изучить интерполяцию, пространственный анализ и/или карты Choropleth. Я думаю, что у них разные алгоритмы в этом. Я чувствую, что мне нужно заполнить больше точек между существующими? И с этим можно сделать градиент как точки? Это возможно в D3? Или мне следует рассмотреть возможность использования материалов three.js или WebGL?

var width = 960,
height = 960;

var map = {};
var projection = d3.geo.mercator()
.scale((width + 1) / 2 / Math.PI)
.translate([width / 2, height / 2])
.precision(.1);

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

var graticule = d3.geo.graticule();

var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);

svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);

d3.json("world-50m.json", function(error, world) {
 svg.insert("path", ".graticule")
  .datum(topojson.feature(world, world.objects.land))
  .attr("class", "land")
  .attr("d", path);

svg.insert("path", ".graticule")
  .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
  .attr("class", "boundary")
  .attr("d", path);
});

map.plot_points = [];
map.max = 30;
map.min = -1;
var opacity = d3.scale.linear()
 .domain([map.min, map.max])
 .range([0,1]);  
var rainbow = ["#CE0C82", "#800CCE", "#1F0CCE", "#0C5BCE", "#0C99CE", "#2ECE0C", "#BAE806", "#FEFF00", "#FFCD00", "#FF9A00", "#FF6000", "#FF0000"];
zs.forEach(function(zv,zi){
    zv.forEach(function(zzv, zzi){
        if(zzv != 999)
            {
                map.plot_points.push({lat: ys[zi], long:xs[zzi],value:zzv});
            }

        })
});
console.log(map);
var points = svg.selectAll("rects.points")
 .data(map.plot_points)
 .enter()
 .append("rect")
 .attr("class", "points")
 .style("fill", function(d) {
   var scale = d3.scale.linear().domain([map.min, map.max]).range([1, rainbow.length]);
        return rainbow[Math.round(scale(d.value))]; 
}).attr("width", 8)
.attr("height", 8)
.style("fill-opacity", 1)
.attr("transform", function(d) {
        return "translate(" + projection([d.long, d.lat]) + ")";
})

person user176855    schedule 06.12.2013    source источник


Ответы (4)


Похоже, проблема в вашем случае - это данные. Что вам нужно сделать, так это взять исходные данные и интерполировать их до более гладкой формы. Для этого вы можете использовать программу ГИС, такую ​​как QGIS. Как именно это сделать, зависит от того, в каком формате находятся исходные данные.

Получив более сглаженные данные, вы можете снова построить их в D3. Я предполагаю, что конечный результат будет чем-то похож на то, что я сделал здесь, где контурные линии нарисованы почти так же, как и то, к чему вы стремитесь.

person Lars Kotthoff    schedule 06.12.2013
comment
Какие алгоритмы используются для сглаживания данных? Я пытался сделать это только через javascript. conrec является ближайшим, однако он работает только с четными точками. - person user176855; 18.12.2013
comment
Я ничего не знаю о Javascript; Я настоятельно рекомендую использовать для этого программу ГИС. - person Lars Kotthoff; 18.12.2013

Может быть, вы могли бы взглянуть на тепловые карты js.

http://www.patrick-wied.at/static/heatmapjs/

Хотя он основан на точках, он может дать вам подсказку. Он использует холст вместо svg.

person Xumo    schedule 06.12.2013

Джейсон Дэвис написал реализацию алгоритма conrec, которая делает именно то, что вам нужно:

https://github.com/jasondavies/conrec.js Внутри есть рабочий пример

person Roger Veciana    schedule 06.12.2013
comment
Я думаю, что conrec.js - это путь или d3.geo.contour(), однако как мне перевести (долготу, широту, значение) или (x, y, значение) во что-то для контура? - person user176855; 10.12.2013
comment
В примере видно, что вам нужны три массива со значениями x, y и value: github.com/jasondavies/conrec.js/blob/master/example/ Я не знаю, был ли это ваш вопрос... - person Roger Veciana; 10.12.2013

Я считаю, что белые полосы появляются из-за используемой вами проекции; На самом деле, высота каждого прямоугольника должна корректироваться соответственно на север и юг от экватора, потому что проекция Меркатора изменяет расстояние на север и юг.
Чтобы иметь фиксированную высоту прямоугольников, вы можете попробовать вместо этого использовать эту проекцию:< br> http://bl.ocks.org/mbostock/3757119
, который сохраняет измерение, идущее на север и юг

person tomtomtom    schedule 06.12.2013