Pergunta

I enlarged a graphicspath using matrix. How can I set that the new path would be exactly over the smaller one and not at the side of it? like the Inflate with rectangles.

Foi útil?

Solução

At its core, GraphicsPath is a number of points with control points that specify how to blend these (when tension is applied). When you apply a matrix operation to the graphics path it updates all these points based on the operation you are performing in the matrix.

That in mind, if I understand the question correctly you might start by getting the bounds of the graphics path:

var graphicsBounds = myPath.GetBounds();

From there you can create a matrix that offsets the bounds to be centered at (0, 0), scales (which will scale in both x/y direction), then offset back to the original location on the screen. This should expand the path symmetrically at the center of the original bounds. That matrix code looks something like:

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

Remember too - matrix order (default) is applied in reverse. So you should read these matrix operations from bottom to top. This might not be exactly right, but at least it should help. Good luck!

Outras dicas

This how I fit graphics into a boundning rectange using a Transform

In this case the code is put in the Paint event of pictureBox1. Sending the bounds of the graphics contained in the GraphicsPath and the picturebox bounds to user function GetMatrixFitRectInBounds() a matrix is returned to be applied to the Graphics.Transform property of the picturebox before drawing.

This illustrates the general idea of using a matrix for transformation:

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;

}

Result:

enter image description here

Since there there maybe lot of computing involved in creating the matrix it could be kept outside the paint and created only when bounds change. The GraphicPath(s) also can be created outside the Paint event and updated only when the underlying data change.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top