C#创建网格捕捉功能

C#创建网格捕捉功能,c#,winforms,runtime,C#,Winforms,Runtime,我试图创建一些在运行时使用的网格捕捉功能,但我在捕捉部分遇到了问题。我已经成功地在面板上绘制了点网格,但是当我向面板添加标签控件时,如何将标签的左上角捕捉到最近的点 谢谢pos.x-pos.x%gridWidth应该可以。只需使用整数和除法即可: int xSnap = (xMouse / gridWidth) * gridWidth; int ySnap = (yMouse / gridHeight) * gridHeight; 当然,模解要优雅得多。这里有一个解决方案,将四舍五入到最近的网

我试图创建一些在运行时使用的网格捕捉功能,但我在捕捉部分遇到了问题。我已经成功地在面板上绘制了点网格,但是当我向面板添加标签控件时,如何将标签的左上角捕捉到最近的点


谢谢

pos.x-pos.x%gridWidth
应该可以。只需使用整数和除法即可:

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

当然,模解要优雅得多。

这里有一个解决方案,四舍五入到最近的网格点:

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

这一个对我来说效果更好,因为它移动点取决于它与下一个或上一个网格点的距离:

            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);
if(pt.X%gridWidth
我认为公认的答案不正确。原因如下:

如果gridwidth=3,则x上的a点(如4)应映射为3,但x=5应映射为6。使用Pedery的答案,他们都将映射到3

为了得到正确的结果,您需要这样四舍五入(如果点是分数,则可以使用浮点):

//比如说

int gridCubeWidth  = 3;
int gridCubeHeight = 3;

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

Kepp记住,上面的代码将捕捉到接近零的网格线。要向左或向右捕捉,您可以测试x位置%gridWidth是否大于或小于gridWidth/2。记住,坐标低于零时,你会得到一个不同的情况。这将为您提供所需的所有工具。如果您有gridWidth=3。对于点X=5,当它应该映射到6时,它将映射到3。请参阅我的答案以获得更详细的答案。这相当于四舍五入,这并不总是理想的结果。舍入到最近的网格顶点是最好的选择,请查看下面@numansalati的答案!您正在用gridWidth进行乘法和除法运算。这将抵消它们,让它们始终等于xMouse。-1:正如@Julian所说,初等数学表明这个答案是无意义的。计算不是初等数学。当“(xMouse/gridWidth)”的结果是一个整数时,这个公式就可以了。谢谢-这就是我要找的