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

int newX = Math.Round(oldX / gridCubeWidth)  * gridCubeWidth;
int newY = Math.Round(oldY / gridCubeHeight) * gridCubeHeight;

Что мне не было интуитивно понятно, так это то, что это не работает с моей диагональной сеткой.

enter image description here

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

0
user6214135 22 Сен 2018 в 17:34

2 ответа

Лучший ответ

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

enter image description here

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

const int SubgridWidth = 40, SubgridHeight = 28;

double newX1 = Snap(oldX, SubgridWidth);
double newY1 = Snap(oldY, SubgridHeight);

double newX2 = SnapShifted(oldX, SubgridWidth);
double newY2 = SnapShifted(oldY, SubgridHeight);

double squareDist1 = SquareDist(oldX, oldY, newX1, newY1);
double squareDist2 = SquareDist(oldX, oldY, newX2, newY2);

if (squareDist1 < squareDist2) {
    // Snap to (newX1, newY1).
} else {
    // Snap to (newX2, newY2).
}

double Snap(double x, double gridSize)
{
    return Math.Round(x / gridSize) * gridSize;
}

double SnapShifted(double x, double gridSize)
{
    return (Math.Round(x / gridSize - 0.5) + 0.5) * gridSize;
}

double SquareDist(double x1, double y1, double x2, double y2)
{
    double dx = x2 - x1;
    double dy = y2 - y1;
    return dx * dx + dy * dy;
}
1
Olivier Jacot-Descombes 24 Сен 2018 в 11:33

Кажется, что на вашем снимке нет углов в 45 градусов.

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

 int newX = (Math.Floor(oldX / HorizontalSpacing) + 0.5) * HorizontalSpacing;
 int newY = (Math.Floor(oldY / VerticalSpacing)  + 0.5) * VerticalSpacing;
0
MBo 23 Сен 2018 в 06:30