Как я могу найти евклидову «зону», на которую падает точка на двумерном графике? - PullRequest
0 голосов
/ 21 марта 2012

Я пытаюсь ускорить свою реализацию A * (очень плохое отставание только при сетке 10x10!), И наихудшее снижение производительности, вероятно, исходит от этой функции:

public Vector2 CoordsToIndex(Vector2 coords)
{
    for (int i = 0; i < mapCols; ++i)
    {
            for (int j = 0; j < mapRows; ++j)
            {
                if (coords.X >= i * map[0, 0].length &&
                    coords.X < i * map[0, 0].length + map[0, 0].length)
                {
                    indexi = i;
                }
                if (coords.Y >= j * map[0, 0].height &&
                    coords.Y < j * map[0, 0].height + map[0, 0].height)
                {
                    indexj = j;
                }
            }
    }
return new Vector2(indexi, indexj);
}

Моя первоначальная реализация не совсем верна, но если я смогу заставить это работать вместо этого, это значительно ускорит процесс (я постоянно использую эту функцию):

// The below math isn't quite right
indexi = (int)((coords.X - (map[0, 0].length / 2)) / map[0, 0].length) - 1;
indexj = (int)((coords.Y - (map[0, 0].height / 2)) / map[0, 0].height) - 1;

if (indexi < 0)
{
    indexi = 0;
}

if (indexj < 0)
{
    indexj = 0;
}

map[0, 0].length - длина плитки, а map[0, 0].height - высота плитки. Все плитки одинаковы.

Должна быть возможность придумать формулу для расчета этого, но я не совсем уверен, что это будет. Любые указатели / помощь / ответы будут оценены!

РЕДАКТИРОВАТЬ: Э-э ... на самом деле я думаю, что проблема может быть вычитание длины или высоты, разделенных на два. Это хорошо для узлов плитки, поскольку я сохраняю их положение как центр плитки, но для этого это вернет неправильную плитку ... возможно, в этом проблема ... проверка.

РЕДАКТИРОВАТЬ: Ах .. это то, что и удалить -1. Чувак, я так растерялся, забавно, как я провел около двух часов прошлой ночью, совершенно смущенный этим, а затем, спустя несколько секунд после того, как я наконец-то отправил справку, ответ приходит ко мне мгновенно.

РЕШЕНИЕ:

public Vector2 CoordsToIndex(Vector2 coords)
{
    int indexi = (int)(coords.X / map[0, 0].length);
    int indexj = (int)(coords.Y / map[0, 0].height);

    return new Vector2(indexi, indexj);
}

Это выглядит намного лучше.

Ответы [ 2 ]

3 голосов
/ 21 марта 2012

Ну, короткий и простой ответ:

indexi = (int)(coords.X/map[0,0].length)
indexj = (int)(coords.Y/map[0,0].height)

РЕДАКТИРОВАТЬ: Конечно, OP редактирует сообщение с почти этим ответом, прежде чем я отправлю это./ Facepalm

1 голос
/ 21 марта 2012

Как насчет этого:

for (int i = 0; i < mapCols; ++i) 
{ 
   if (coords.X >= i * map[0, 0].length && 
       coords.X < i * map[0, 0].length + map[0, 0].length) 
   { 
     indexi = i;
     break; // no need to continue the loop
   } 
} 
for (int j = 0; j < mapRows; ++j) 
{ 
  if (coords.Y >= j * map[0, 0].height && 
      coords.Y < j * map[0, 0].height + map[0, 0].height) 
  { 
    indexj = j; 
    break; // no need to continue the loop
  } 
} 

Обратите внимание, что в исходном коде вы циклически просматриваете каждую ячейку, чтобы найти строку и столбец, когда вам нужно только циклически пройти строки, чтобы найти строкуиндекс (и аналогично для столбца).Таким образом, вместо 100 сравнений, теперь у вас есть 20 (самое большее).

РЕДАКТИРОВАТЬ: И, конечно, ваше собственное решение

int indexi = (int)(coords.X / map[0, 0].length); 
int indexj = (int)(coords.Y / map[0, 0].height); 

намного более оптимально:

...