【问题标题】:Matrix and graphicspath矩阵和图形路径
【发布时间】:2013-12-25 01:52:05
【问题描述】:

我使用矩阵扩大了图形路径。如何设置新路径正好在较小的路径上而不是在它的一侧?就像带有矩形的 Inflate。

【问题讨论】:

    标签: c# graphics matrix rectangles graphicspath


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      这就是我如何使用 Transform 将图形放入边界矩形中

      在这种情况下,代码放在pictureBox1 的Paint 事件中。将 GraphicsPath 中包含的图形边界和图片框边界发送给用户函数 GetMatrixFitRectInBounds() 会返回一个矩阵,以便在绘制之前将其应用于图片框的 Graphics.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(s) 也可以在 Paint 事件之外创建,并且仅在基础数据更改时更新。

      【讨论】:

      • 注意缩放也会缩放线宽。要保持原始笔宽,您可以在绘制到缩放图形之前通过反向缩放笔宽来取消它,如下所示:Pen myPen = new Pen(Color.Blue, linewidth/scale).
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多