pictureBox1变形后如何获取XY
How to get XY of pictureBox1 after it has been transformed
我有一个在 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);
}
}
您可以创建一个具有必要转换的矩阵,并通过 MultiplyTransform(...) 在 pictureBox1_Paint(...) 中应用它:
https://msdn.microsoft.com/en-us/library/bt34tx5d(v=vs.110).aspx
然后你可以使用 Matrix::TransformPoints(...) 得到转换后的 XY
作为@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()
函数不能很好地用于此目的,因为它仅将状态放在 stack 上以供使用 once,这意味着它不会以持久的方式保存这些数据。
稍后您可以使用 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
对象。 (虽然上次测试并没有绘制旋转的较大矩形,只是移动到正确的位置。)
另请注意,我 return 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];
最后:非常值得学习many methods of Matrix..!
我有一个在 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);
}
}
您可以创建一个具有必要转换的矩阵,并通过 MultiplyTransform(...) 在 pictureBox1_Paint(...) 中应用它:
https://msdn.microsoft.com/en-us/library/bt34tx5d(v=vs.110).aspx
然后你可以使用 Matrix::TransformPoints(...) 得到转换后的 XY
作为@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()
函数不能很好地用于此目的,因为它仅将状态放在 stack 上以供使用 once,这意味着它不会以持久的方式保存这些数据。
稍后您可以使用 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
对象。 (虽然上次测试并没有绘制旋转的较大矩形,只是移动到正确的位置。)
另请注意,我 return 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];
最后:非常值得学习many methods of Matrix..!