【发布时间】:2015-03-08 10:22:14
【问题描述】:
我正在尝试使用单个全局矩阵实现关于固定点的缩放。运行时,如果单击控件,它会缩放,但每次单击时测试矩形会进一步向下和向右移动。 据我所知,每个转换(到原点、比例和返回到原始位置)单独工作正常,但是当我将所有 3 个转换在一起时,我没有得到正确的行为。
缩放代码
当点击控件时,代码(应该)转换为原点,放大一个因子,然后转换回原始位置。
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
float xPos = e.Location.X - viewMatrix.OffsetX;
float yPos = e.Location.Y - viewMatrix.OffsetY;
Matrix translateOrigin = new Matrix(1, 0, 0, 1, -xPos, -yPos);
Matrix translateBack = new Matrix(1, 0, 0, 1, xPos, yPos);
Matrix scaleMatrix = new Matrix(1.5f, 0, 0, 1.5f, 0, 0);
viewMatrix.Multiply(translateOrigin);
viewMatrix.Multiply(scaleMatrix);
viewMatrix.Multiply(translateBack);
}
else
{
viewMatrix = new Matrix();
}
Refresh();
}
绘图代码
这是我用来绘制的代码。这两个矩形仅供参考,new Pen(2) 上的第二个值是为了确保我的线条保持 1 像素宽。
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
GraphicsState gState = e.Graphics.Save();
e.Graphics.MultiplyTransform(viewMatrix);
e.Graphics.DrawRectangle(new Pen(Color.Pink, 1.0f / viewMatrix.Elements[3]), -5, -5, 10, 10);
e.Graphics.DrawRectangle(new Pen(Color.Pink, 1.0f / viewMatrix.Elements[3]), 20, 20, 10, 10);
e.Graphics.Restore(gState);
}
编辑
在休息了一天(或两天)之后再次查看代码,我意识到我脑子里有一个错误的想法(这就是我在一天结束时试图弄清楚这一点的结果)。我正在寻找的行为是视图将随着单击点保持在同一位置而缩放。例如,如果我单击其中一个矩形的右下角,则视图将对其进行缩放,同时将右下角保持在鼠标下方。
编辑 2
在@TaW 的大量帮助下,我得到了以下代码,该代码将缩放并保持鼠标下的点固定。
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
//Get the inverse of the view matrix so that we can transform the mouse point into the view
Matrix viewMatrixRev = viewMatrix.Clone();
viewMatrixRev.Invert();
//Translate the mouse point
PointF mousePoint = e.Location;
viewMatrixRev.TransformPoints(new PointF[] { mousePoint });
//Transform the view
viewMatrix.Translate(-mousePoint.X, -mousePoint.Y, MatrixOrder.Append);
viewMatrix.Scale(zoom, zoom, MatrixOrder.Append);
viewMatrix.Translate(mousePoint.X, mousePoint.Y, MatrixOrder.Append);
}
else
{
viewMatrix = new Matrix();
}
Refresh();
}
【问题讨论】:
-
您是否真的尝试测试过这个
viewMatrixRev.TransformPoints(new PointF[] { mousePoint });部分??这是对我的代码的简化,但我无法让它工作;结构是值类型,在转换数组中放置一个似乎只是创建一个副本,然后被丢弃..???花了我一个小时才知道.. -
嗯....我现在更困惑了。它确实对我有用,但你是对的,如果我单步执行代码
mousePoint在调用转换后不会改变。所以我尝试了一些东西并完全删除了翻译mousePoint的代码,它也能正常工作 -
嘿嘿,也许再睡个好觉?
-
我意识到这就是 Ripple 想要表达的意思。不知何故,我一定是搞砸了他/她的解决方案,并认为它不起作用
-
@amura.cxg 很高兴您完成了目标。绘制的对象和鼠标光标在同一个坐标系中,所以不需要变换鼠标坐标。这些事情对我来说总是很难解释。对不起,如果我的英语很差而且没有解释让你感到困惑。