开发者

C# Create Snap To Grid Functionality

I am trying to create some snap to grid functionality to be used at run time but I am having problems with the snapping part. I have successfully drawn a dotted grid on a panel but when I add a label control to the panel how to I snap the 开发者_运维百科top, left corner of the label to the nearest dot?

Thanks


I don't think the accepted answer is correct. Here is why:

if the gridwidth = 3, the a point on x like 4 should map to 3 but x=5 should map to 6. using Pedery's answer they will both map to 3.

For correct result you need to round off like this (you can use float if points are fractions):

//Lets say.

int gridCubeWidth  = 3;
int gridCubeHeight = 3;

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


pos.x - pos.x % gridWidth should do it.


This one works better for me as it moves the point depending on how close it is to next or previous gird-point:

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


Here is a solution that rounds to the nearest grid point:

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


Just use integers and division will just work for you:

int xSnap = (xMouse / gridWidth) * gridWidth;
int ySnap = (yMouse / gridHeight) * gridHeight;

Except of course the modulo solution is so much more elegant.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜