Как реализовать предотвращение столкновений точек в d3.js v5? - PullRequest
0 голосов
/ 17 апреля 2019

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

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

Все реализации, которые я пробовал, использовали функцию forceSimulation с силой столкновения.

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

начало данных: data = [{x:num, y:num, radius:num, xstart:num, ystart:num}, ...]

   var data = [];
   for (var x =0; x < positions.length; x++) {
       data.push({
           "xstart": positions[x][0],
           "ystart": positions[x][1],

       });
    }
  data.forEach(function(d) {
    d.x = xscale(d.xstart);
    d.y = yscale(d.ystart);
    d.radius = radius;
  });

создание точек:

var dots = g.selectAll("scatter-dots");

dots
    .data(data)
    .enter().append("circle")
        .attr("cx", function (d) { return d.x; } )
        .attr("cy", function (d) { return d.y; } )
        .attr("r", radius)
        // additional attributes
        .each(function (d, i) {
            d3.select(this)
                .attr("id", "poslanec_"+i)
                .attr("class", "poslanec")
                .append("title")
                    .text(osoby[keys[o][i]]["cele_jmeno"]);
        });

проблемная часть: предотвращение столкновений

var simulation = d3.forceSimulation(data)
        .force("collision", d3.forceCollide(radius))
        .on("tick", update);

function update () {
    dots
        .attr("cx", function(d) {return d.x;})
        .attr("cy", function(d) {return d.y;});

// this log prints an unchanged array
   console.log(this.nodes());
}

Я ожидал, что каждая точка столкновения будет немного смещена в сторону (в соответствии с radius), поэтому ни одна точка не будет перекрываться и касаться только своих соседей.

Заранее благодарим вас за любые идеи!

1 Ответ

0 голосов
/ 18 апреля 2019

Я обнаружил, что из определенной версии оси точки не обновляются автоматически, а сохраняются в vx / vy, что является скоростью;поэтому решение состоит в том, чтобы вычесть скорость из оси.

Мое решение, даже если оно не очень красивое:

function update () {
    var nodes = this.nodes();
    nodes.forEach(function (d, i) {
        //selecting by an id of a point
        d3.select('#poslanec_'+nodes[i].id)
            .attr("cx", (nodes[i]["x"] - nodes[i]["vx"]))
            .attr("cy", (nodes[i]["y"] - nodes[i]["vy"]));
    });     
}
...