C# 矩阵与图形

C# 矩阵与图形,c#,graphics,matrix,rectangles,graphicspath,C#,Graphics,Matrix,Rectangles,Graphicspath,我用矩阵放大了一幅图。我如何设置新路径正好位于较小路径之上,而不是位于其一侧?与使用矩形充气一样。在其核心,GraphicsPath是一系列带有控制点的点,这些控制点指定如何混合这些点(当施加张力时)。将矩阵操作应用于图形路径时,它会根据在矩阵中执行的操作更新所有这些点 请记住,如果我正确理解了问题,您可以从获取图形路径的边界开始: var graphicsBounds = myPath.GetBounds(); 从那里,您可以创建一个矩阵,将边界偏移到(0,0)的中心,缩放(将在x/y方向上

我用矩阵放大了一幅图。我如何设置新路径正好位于较小路径之上,而不是位于其一侧?与使用矩形充气一样。

在其核心,GraphicsPath是一系列带有控制点的点,这些控制点指定如何混合这些点(当施加张力时)。将矩阵操作应用于图形路径时,它会根据在矩阵中执行的操作更新所有这些点

请记住,如果我正确理解了问题,您可以从获取图形路径的边界开始:

var graphicsBounds = myPath.GetBounds();
从那里,您可以创建一个矩阵,将边界偏移到(0,0)的中心,缩放(将在x/y方向上缩放),然后偏移回屏幕上的原始位置。这将在原始边界的中心对称扩展路径。该矩阵代码类似于:

Matrix myMatrix = new Matrix();

myMatrix.TranslateTransform(graphicsBounds.X + graphicsBounds.Width/2.0f, graphicsBounds.Y + graphicsBounds.Height/2.0f);
myMatrix.Scale(scaleX, scaleY);
myMatrix.TranslateTransform(-graphicsBounds.X - graphicsBounds.Width/2.0f, -graphicsBounds.Y - graphicsBounds.Height/2.0f);

也请记住-矩阵顺序(默认)是反向应用的。所以你应该从下到上阅读这些矩阵运算。这可能并不完全正确,但至少应该有所帮助。祝你好运

这就是我如何使用变换将图形适配到边界矩形中的方法

在这种情况下,代码放入pictureBox1的绘制事件中。将GraphicsPath和picturebox bounds中包含的图形边界发送到用户函数GetMatrixFitterInBounds()时,将返回一个矩阵以应用于图形。在绘制之前,picturebox的Transform属性

这说明了使用矩阵进行转换的一般思路:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    //GraphicsPath is a great to store for graphics if repainted frequently
    var myPath = new GraphicsPath();

    //Add simple ellipse
    myPath.AddEllipse(new Rectangle(0, 0, 50, 50));

    //Get transform to fit a rectange within a bounding rectange 
    var T = GetMatrixFitRectInBounds(myPath.GetBounds(), new RectangleF(pictureBox1.ClientRectangle.Location, pictureBox1.ClientRectangle.Size));

    //Apply transformation matrix
    e.Graphics.Transform = T;

    // Create a pen for the path
    Pen myPen = new Pen(Color.Black, 1);

    //Draw path to picturebox
    e.Graphics.DrawPath(myPen, myPath); 
}
-

//Return Matrix to scale a rectange within a rectangle
private Matrix GetMatrixFitRectInBounds(RectangleF fitrect, RectangleF boundsrect)
{
    var T = new Matrix();

    var bounds_center = new PointF(boundsrect.Width / 2, boundsrect.Height / 2);

    //Set translation centerpoint
    T.Translate(bounds_center.X, bounds_center.Y);

    //Get smallest size to scale to fit boundsrect
    float scale = Math.Min(boundsrect.Width / fitrect.Width, boundsrect.Height / fitrect.Height);

    T.Scale(scale, scale);

    //Move fitrect to center of boundsrect
    T.Translate(bounds_center.X - fitrect.X - fitrect.Width / 2f, bounds_center.Y - fitrect.Y - fitrect.Height / 2f);

    //Restore translation point
    T.Translate(-bounds_center.X, -bounds_center.Y);

    return T;

}
结果:


因为在创建矩阵时可能会涉及很多计算,所以可以将其保留在画图之外,并且只有在边界发生变化时才能创建。GraphicPath也可以在Paint事件之外创建,并仅在基础数据更改时更新。

注意缩放也会缩放线宽。要保持原始笔宽,您可以在绘制成以下缩放图形之前通过反向缩放笔宽来取消它:
pen myPen=new pen(Color.Blue,linewidth/scale)