Ответ 1
pos.x - pos.x% gridWidth должен сделать это
Я пытаюсь создать некоторые привязки к сетке, которые будут использоваться во время выполнения, но у меня возникают проблемы с частью привязки. Я успешно нарисовал пунктирную сетку на панели, но когда я добавлю элемент управления меткой на панель, как я привяжу верхний левый угол метки к ближайшей точке?
Спасибо
pos.x - pos.x% gridWidth должен сделать это
Я не думаю, что принятый ответ правильный. Вот почему:
если ширина сетки = 3, точка на x, как 4, должна отображаться в 3, но x = 5 должна отображаться в 6. Используя ответ Pedery, они оба будут отображаться в 3.
Для правильного результата вам нужно округлить, как это (вы можете использовать float, если точки являются фракциями):
//Давайте скажем.
int gridCubeWidth = 3;
int gridCubeHeight = 3;
int newX = Math.Round(oldX / gridCubeWidth) * gridCubeWidth;
int newY = Math.Round(oldY / gridCubeHeight) * gridCubeHeight;
Вот решение, которое округляет до ближайшей точки сетки:
public static readonly Size Grid = new Size( 16, 16 );
public static readonly Size HalfGrid = new Size( Grid.Width/2, Grid.Height/2 );
// ~~~~ Round to nearest Grid point ~~~~
public Point SnapCalculate( Point p )
{
int snapX = ( ( p.X + HalfGrid.Width ) / Grid.Width ) * Grid.Width;
int snapY = ( ( p.Y + HalfGrid.Height ) / Grid.Height ) * Grid.Height;
return new Point( snapX, snapY );
}
private enum SnapMode { Create, Move }
private Size gridSizeModeCreate = new Size(30, 30);
private Size gridSizeModeMove = new Size(15, 15);
private Point SnapCalculate(Point p, Size s)
{
double snapX = p.X + ((Math.Round(p.X / s.Width) - p.X / s.Width) * s.Width);
double snapY = p.Y + ((Math.Round(p.Y / s.Height) - p.Y / s.Height) * s.Height);
return new Point(snapX, snapY);
}
private Point SnapToGrid(Point p, SnapMode mode)
{
if (mode == SnapMode.Create)
return SnapCalculate(p, gridSizeModeCreate);
else if (mode == SnapMode.Move)
return SnapCalculate(p, gridSizeModeMove);
else
return new Point(0, 0);
}
Это работает лучше для меня, поскольку оно перемещает точку в зависимости от того, насколько близко она находится к следующей или предыдущей граничной точке:
if (pt.X % gridWidth < gridWidth/2)
pt.X = pt.X - pt.X % gridWidth;
else
pt.X = pt.X + (gridWidth - pt.X % gridWidth);
if (pt.Y % gridHeight < gridHeight / 2)
pt.Y = pt.Y - pt.Y % gridHeight;
else
pt.Y = pt.Y + (gridHeight - pt.Y % gridHeight);
Просто используйте целые числа и деление только для вас:
int xSnap = (xMouse / gridWidth) * gridWidth;
int ySnap = (yMouse / gridHeight) * gridHeight;
Кроме того, модульное решение намного элегантнее.