Точки на графике, чтобы они не перекрывались, если они имеют одинаковые координаты - PullRequest
1 голос
/ 16 апреля 2010

У меня есть функция, которая принимает долготу и широту и преобразует ее в x и y для построения графика. Преобразование в X и Y работает нормально, и это не то, с чем у меня проблема.

Я хочу убедиться, что две точки не отображаются в одном месте. В одном наборе результатов около 30 друг над другом (поскольку они имеют одинаковую широту и долготу), это число может быть намного больше.

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

Код - Javascript, но он очень общий, поэтому я думаю, что он немного не имеет значения.

Мой код выглядит следующим образом:

var prevLong, prevLat, rand = 1, line = 1, spread = 8, i = 0;

function plot_points(long, lat){

    // CODE HERE TO CONVERT long and lat into x and y

    // System to not overlap the points 
    if((prevLat == lat) &&  (prevLong == long)) {

        if(rand==1) {
            x += spread*line;
        } else if(rand==2) {
            x -= spread*line;
        }   else if(rand==3) {
            y += spread*line;
        }   else if(rand==4) {
            y -= spread*line;
        }   else if(rand==5) {
            x += spread*line;
            y += spread*line;
        }   else if(rand==6) {
            x -= spread*line;
            y -= spread*line;
        }   else if(rand==7) {
            x += spread*line;
            y -= spread*line;
        }   else if(rand==8) {
            x -= spread*line;
            y += spread*line;
        // x = double
        }   else if(rand==9) {
            x += spread*line;
            y += spread;
        }   else if(rand==10) {
            x += spread;
            y += spread*line;
        }   else if(rand==11) {
            x -= spread*line;
            y -= spread;
        }   else if(rand==12) {
            x -= spread;
            y -= spread*line;
        }   else if(rand==13) {
            x += spread*line;
            y -= spread;
        }   else if(rand==14) {
            x += spread;
            y -= spread*line;
        }   else if(rand==15) {
            x += spread*line;
            y -= spread;
        }   else if(rand==16) {
            x += spread;
            y -= spread*line;
        } else if(rand==17) {
            x -= spread*line;
            y += spread;
        }   else if(rand==18) {
            x -= spread;
            y += spread*line;
        }   else if(rand==19) {
            x -= spread*line;
            y += spread;
        }   else if(rand==20) {
            x -= spread;
            y += spread*line;
        }

        if(rand == 20) {rand = 1; line++; } else { rand++;  }
        i++
    } else {

        line = 1;
        i = 0; 

    }

    prevLat = latitude;
    prevLong = longitude;

    return [x,y];

}

Это вывод: output

Это работает неправильно, и я даже не знаю, правильно ли я подхожу к проблеме.

Кто-нибудь должен был делать это раньше? Какой метод вы бы предложили?

Ответы [ 2 ]

1 голос
/ 17 апреля 2010

Используя решение Эрнелли в качестве примера, мне удалось заставить графику работать правильно. Кажется, немного затянуто, но работает и не медленно.

Решение Эрнелли имеет ошибку во втором цикле for:

for(j = 0; i < height; i++)

Должно быть:

for(j = 0; j < height; j++)

В любом случае, это мой код, который я использую, и он работает. pointArray - это массив всех элементов, которые должны быть нанесены на график:

var countArray = new Array();

// Go through every point and group same co-ordinates together 
for (var i = pointArray.length-1; i > -1; i--) {
    if(pointArray[i] != undefined) 
    { 
        var found = 0;

        // Check if this point is already in array
        for (var j = countArray.length-1; j > -1; j--)
        {
            if(countArray[j] != undefined)
            {
                if((pointArray[i].getBBox().x == countArray[j]["x"]) && (pointArray[i].getBBox().y == countArray[j]["y"]))
                {
                    countArray[j]["points"].push(pointArray[i]);
                    found = 1;
                }
            } 
        }

        // The point is not in the array, so add it
        if(found != 1) 
        {
            var index = countArray.length;
            countArray[index] = new Array();
            countArray[index]["x"] = pointArray[i].getBBox().x;
            countArray[index]["y"] = pointArray[i].getBBox().y;
            countArray[index]["points"] = new Array();
            countArray[index]["points"].push(pointArray[i]);
        }

    }
}

// For each co-ordinate
for (var j = countArray.length-1; j > -1; j--)
{
    if(countArray[j] != undefined)
    {   
        // If there is more than one point
        if(countArray[j]["points"].length > 1) {

            // Calculate the square points
            var count = countArray[j]["points"].length;
            var x = countArray[j]["x"];
            var y = countArray[j]["x"];
            result = [];

            var width = count/Math.sqrt(count);
            width = Math.floor(width);
            height = Math.floor(count/width);
            var remain = count % width;


            var i2,j2, xx, yy;
            var space = 8;
            for(i2 = 0; i2 < width*space; i2+=space)
            {
              for(j2 = 0; j2 < height*space; j2+=space)
                {
                result.push([(Math.floor(width/2)+i2), (Math.floor(height/2)+j2)]); 
                }   
            }
            for(i2 = 0; i2 < remain*space; i2+=space)
            {
              result.push([(Math.floor(width/2)+i2), (Math.floor(height/2)+j2)]);
            }

            // Go through each point and then translate it to it's new position
            for (var jj = countArray[j]["points"].length-1; jj > -1; jj--)
            {
                if(countArray[j]["points"][jj] != undefined)
                {
                    if(result[jj] != undefined)
                    {   
                        countArray[j]["points"][jj].translate(result[jj][0]-((width*8)/2), result[jj][1]-((height*8)/2))
                    }
                }
            }
        } // End if count more than 1
    } // End if undefined
}

Обратите внимание, что здесь используются многие raphael.js функции (такие как getBBox и translate)

1 голос
/ 16 апреля 2010

Начните с группировки ваших координат. Ваше длинное, lat -> x, y преобразование может не понадобиться до последнего шага. Одним из методов является создание хеш-карты, в которой вы сохраняете каждую позицию long / lat и счетчик для каждой позиции.

Затем вы конвертируете каждую длинную позицию lat в координаты x, y и с помощью счетчика решаете, как отобразить точки с центром вокруг позиции x, y, но с размером, соответствующим количеству точек.

Рабочий алгоритм рендеринга квадрата:

var count = 30; // example
result = [];

var width = count/Math.sqrt(count);
width = Math.floor(width);
height = Math.floor(count/width);
var remain = count % width;

var i,j;

for(i = 0; i < width; i++)
  for(j = 0; j < height; j++)
    result.push([x-Math.floor(width/2)+i, y-Math.floor(height/2)+j]; 
for(i = 0; i < remain; i++)
  result.push([x-Math.floor(width/2)+i, y-Math.floor(height/2)+j];

Входные данные - это число точек, координаты x, y по центру, выходные данные - это массив точек для визуализации.

Последняя строка - это оставшиеся точки, например, квадрат с 15 точками отображает:

OOOO
OOOO
OOOO
OOO
...