如何在转换后得到pictureBox1的XY



我有一个在pictureBox1上绘制的点列表。

pictureBox1已被转换。

现在,当我将鼠标悬停在任何绘制的点上时,我想获得绘制的点的XY坐标。

当我将鼠标悬停在pictureBox1上时,我得到的是pictureBox的XY,而不是转换后的XY。

你能帮我找到变换后的XY吗?

感谢
    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        int height = pictureBox1.ClientSize.Height / 2;
        int width = pictureBox1.ClientSize.Width / 2;            
        //=====
        //scale
        //=====
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.TranslateTransform(-width, -height);
        e.Graphics.ScaleTransform(2f, 2f);
        //===========
        //draw center
        //===========
        e.Graphics.DrawLine(new Pen(Color.Black, 0.5f), new Point(width - 2, height), new Point(width + 2, height));
        e.Graphics.DrawLine(new Pen(Color.Black, 0.5f), new Point(width, height - 2), new Point(width, height + 2));
        //===========
        //draw points
        //===========
        foreach (var p in Points)
        {
            Point[] pts = new Point[] { new Point(p.X, p.Y) };
            Rectangle rc = new Rectangle(pts[0], new Size(1, 1));
            e.Graphics.DrawRectangle(Pens.Red, rc);
        }
    }

作为@Vitaly的答案的变体,您可以这样做:

在对Graphics对象进行变换后,可以将其变换矩阵e.Graphics.Transform保存在一个变量中:

Matrix matrix = null;
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    int height = pictureBox1.ClientSize.Height / 2;
    int width = pictureBox1.ClientSize.Width / 2;
    //=====
    //scale
    //=====
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.TranslateTransform(-width, -height);
    e.Graphics.ScaleTransform(2f, 2f);
    matrix = e.Graphics.Transform;   // save the transformation matrix!
    ...

这是必要的,因为在Paint事件后转换数据丢失了!注意,GraphicsState graphics.Save()&Restore()函数不能很好地用于此目的,因为它只将状态放在堆栈上,以便使用它一次,这意味着它不会以持久的方式保存这些数据。

之后,你可以使用Matrix和这个函数用相同的矩阵变换Points或反向变换,例如,对于鼠标坐标:

PointF transformed(Point p0, bool forward)
{
    Matrix m = matrix.Clone();
    if (!forward)  m.Invert(); 
    var pt = new Point[] { p0 };
    m.TransformPoints(pt);
    return pt[0];
}

现在我的MouseMove事件显示了原始和重新转换的位置:

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    label1.Text = e.Location + " <-> " + transformed(e.Location, false) ;
}

为了测试前向转换,你可以在Paint事件的末尾添加以下内容:

e.Graphics.ResetTransform();
for (int i = 0; i < Points.Count; i++)
{
    Point[] pts = new Point[] { Point.Round(transformed(Points[i], true)) };  
    Rectangle rc = new Rectangle(pts[0], new Size(19, 19));
    e.Graphics.DrawRectangle(Pens.Red, rc);
}

首先清除所有的转换,然后通过调用转换后的函数在相同的位置绘制更大的Rectangles

注意,这也适用于旋转的Graphics对象。(虽然最后一个测试没有绘制较大的矩形旋转,只是移动到正确的位置。)

还请注意,我返回PointF是为了在缩放分数时获得更好的精度。您可以使用Point.Round(或Point.Truncate)来获得Point

请查看Matrix.Elements:它们包含您使用的数字:

float scaleX = matrix.Elements[0];
float scaleY = matrix.Elements[3];
float transX = matrix.Elements[4];
float transY = matrix.Elements[5];

最后:矩阵的许多方法值得研究…!

你可以创建一个矩阵与必要的转换,并应用它在pictureBox1_Paint(…)通过MultiplyTransform(…):

https://msdn.microsoft.com/en-us/library/bt34tx5d (v = vs.110) . aspx

然后你可以使用Matrix::TransformPoints(…)来转换XY

相关内容

  • 没有找到相关文章

最新更新