简体   繁体   English

如何在转换后获得pictureBox1的XY

[英]How to get XY of pictureBox1 after it has been transformed

I have a list of Points that have been drawn on pictureBox1. 我有一个在pictureBox1上绘制的点列表。

pictureBox1 has been transformed. pictureBox1已被改造。

Now, I want to get XY coordinates of the point that was drawn as I hover over any drawn point. 现在,我希望得到当我将鼠标悬停在任何绘制点上时绘制的点的XY坐标。

When I hover over the pictureBox1, I am getting the XY of the pictureBox -- not a transformed XY. 当我将鼠标悬停在pictureBox1上时,我得到了pictureBox的XY - 而不是转换后的XY。

Can you help me get to the transformed XY? 你能帮助我进入变形后的XY吗?

Thanks 谢谢

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

You can create a Matrix with necessary transformations and apply it in pictureBox1_Paint(...) via MultiplyTransform(...): 您可以使用必要的转换创建矩阵,并通过MultiplyTransform(...)将其应用于pictureBox1_Paint(...):

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

Then you can use Matrix::TransformPoints(...) to get transformed XY 然后你可以使用Matrix :: TransformPoints(...)来获得变换后的XY

As a variation to @Vitaly's answer you can do this: 作为@Vitaly答案的变体,您可以这样做:

After transforming the Graphics object you can save its transformation matrix e.Graphics.Transform in a variable: 转换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!
    ...

This is necessary as the transfomation data are lost after the Paint event! 这是必要的,因为转换数据在Paint事件后丢失了! Note that the GraphicsState graphics.Save()&Restore() functions can't be used very well for this purpose, as it only puts the state on the stack for using it once , meaning it doesn't save these data in a persistent way. 请注意, GraphicsState graphics.Save()&Restore()函数不能很好地用于此目的,因为它只将状态放在堆栈上以便使用它一次 ,这意味着它不会以持久的方式保存这些数据。

Later you can use the Matrix and this function to either transform Points with the same matrix or reverse the transformation, eg for mouse coordinates: 之后你可以使用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];
}

Now my MouseMove event shows the location both raw and re-transformed: 现在我的MouseMove事件显示了原始位置和重新转换的位置:

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

And to test the forward transformation you could add this to the end of the Paint event: 要测试正向转换,您可以将其添加到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);
}

This first clears all the transformations and then paints larger Rectangles at the same locations by calling the transformed function. 首先清除所有变换,然后通过调用变换函数在相同位置绘制较大的Rectangles

Note that this will also work with a rotated Graphics object. 请注意,这也适用于旋转的Graphics对象。 (Although the last test does not draw the larger rectangles rotated, just moved to the right locations.) (虽然最后一次测试不会绘制更大的矩形旋转,但只是移动到正确的位置。)

Also note that I return PointF for better precision when scaling with fractions. 另请注意,在使用分数缩放时,我返回PointF以获得更好的精度。 You can use Point.Round (or Point.Truncate ) to get Point . 您可以使用Point.Round (或Point.Truncate )来获取Point

Do have a look the the Matrix.Elements : They contain the numbers you have used: 看看Matrix.Elements :它们包含您使用过的数字:

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

Finally: It is well worth studying the many methods of Matrix ..! 最后:非常值得研究Matrix许多方法 ..!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM