Как повернуть (x, y) для привязки к сетке

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

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

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

введите описание изображения здесь

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

2 ответа

Решение

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

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

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;
}

Кажется, на твоей картинке нет 45-градусных углов.

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

 int newX = (Math.Floor(oldX / HorizontalSpacing) + 0.5) * HorizontalSpacing;
 int newY = (Math.Floor(oldY / VerticalSpacing)  + 0.5) * VerticalSpacing;
Другие вопросы по тегам