2

私はこれに少し戸惑っていますが、マウスがグリッドにスナップすることに頭を悩ませようとする問題があります。現在、私はOnRenderそのようにオーバーライドしてグリッドを描いています。

 protected override void OnRender(DrawingContext drawingContext)
        {

            int numberOfVerticalLines = 8;
            int numberOfHorizontalLines = 8;

            CellHeight = this.ActualHeight / numberOfVerticalLines;
            CellWidth = this.ActualWidth / numberOfHorizontalLines;

            double verticalOffset = 0;
            double horizontalOffset = 0;

            Pen pen = new Pen(Stroke, StrokeThickness);

            pen.DashStyle = DashStyle;

            for (int i = 0; i <= numberOfHorizontalLines; i++)
            {
                for (int j = 0; j <= numberOfVerticalLines; j++)
                {

                    drawingContext.DrawLine(pen, new Point(horizontalOffset, verticalOffset), new Point(horizontalOffset, CellHeight + verticalOffset));

                    verticalOffset += CellHeight;
                }

                horizontalOffset += CellWidth;
                verticalOffset = 0;
            }

            horizontalOffset = 0;
            verticalOffset = 0;

            for (int i = 0; i <= numberOfVerticalLines; i++)
            {
                for (int j = 0; j <= numberOfHorizontalLines; j++)
                {
                    drawingContext.DrawLine(pen, new Point(horizontalOffset, verticalOffset), new Point(CellWidth + horizontalOffset, verticalOffset));

                    horizontalOffset += CellWidth;
                }

                verticalOffset += CellHeight;
                horizontalOffset = 0;
            }
        }

そして、次の結果が得られます。

グリッドの例

ただし、マウスを最も近いグリッドの交点 (水平線と垂直線が交わる場所) にスナップするためのルートを考えるのに少し苦労しています。明らかに、私は描画コンテキストを使用して線を描画しているので、描画された後はこれらの線を参照していません。

だから私は本質的に私の質問は、マウススナップをグリッドに実装するにはどうすればよいですか? これは、オブジェクト指向の制御に関する質問というよりも、数学に関する質問ですか? 関連するスタック オーバーフローの質問をほぼすべて読みましたが、まだ現実的なアイデアにたどり着くことができませんでした。

注: 現時点では 8x8 グリッドをハードコーディングしましたが、これは最終的にユーザー定義になります。

4

3 に答える 3

2

基本的なアプローチは、次の方法でマウスの (x,y) を十字と比較することです。1. マウスが配置されているセルの幅と高さの始点と終点を計算します。2. これらの 2 つの間隔 (幅と高さ) を実際のマウス (x,y) と比較して、最も近いセル ポイントを見つけます。

以下は、スナッピングを示すためにいくつかのサンプル コードを簡単にまとめたものです。

/// <summary>
/// When left shift key is pressed we snap the mouse to the closest
/// intersection
/// </summary>
void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.LeftShift)
    {
        var p = GetSnappingPoint(Mouse.GetPosition(this), new Size(200, 200));
        SetCursorPos((int)p.X, (int)p.Y+20);
    }

}

[DllImport("User32.dll")]
private static extern bool SetCursorPos(int x, int y);

/// <summary>
/// Get snapping point by
/// </summary>
Point GetSnappingPoint(Point mouse,Size cellSize)
{
    //Get x interval based on cell width
    var xInterval = GetInterval(mouse.X, cellSize.Width);

    //Get y interal based in cell height
    var yInterval = GetInterval(mouse.Y, cellSize.Height);

    // return the point on cell grid closest to the mouseposition
    return new Point()
    {
        X = Math.Abs(xInterval.Lower - mouse.X) > Math.Abs(xInterval.Upper - mouse.X) ? xInterval.Upper : xInterval.Lower,
        Y = Math.Abs(yInterval.Lower - mouse.Y) > Math.Abs(yInterval.Upper - mouse.Y) ? yInterval.Upper : yInterval.Lower,
    };
}

/// <summary>
///  Find an interval of the celsize based on mouse position and size
/// </summary>
Interval GetInterval(double mousePos,double size)
{
    return new Interval()
    {
        Lower = ((int)(mousePos / size)) * size,
        Upper = ((int)(mousePos / size)) * size + size
    };
}

/// <summary>
/// Basic interval class
/// </summary>
class Interval
{
    public double Lower { get; set; }
    public double Upper { get; set; }
}
于 2013-07-10T15:38:17.627 に答える
1

答えへの大まかなスタート:

int nearGridX = CellWidth * Math.Round( mouseX / CellWidth);
int nearGridY = CellHeight * Math.Round( mouseY / CellHeight);
于 2013-07-10T15:36:40.017 に答える
0
xPos= mouseX - (mouseX % gridWidth);
yPos= mouseY - (mouseY % gridHeight);

これにより、現在のグリッドの左上隅にすばやく汚いスナップができます。これは、現在のグリッドの下部または右側に近い場合は考慮されません。あなたがいるグリッドを見て、そこにドロップするだけです。

于 2016-04-21T18:10:09.837 に答える