Search code examples
c#drawing2d

How to rotate 2d object in C#


Basically i have a windows form that user will be able to draw different shapes(e.g square, circle and triangle), user will be able to highlight any of these shapes after drawing and then control that highlighted shape by moving or rotating it, i don't know how to rotate the shape. any one can help, this is my code (only to draw a square) PS: user need to click twice on the form to draw the shape between those 2 points as shown below also i know i should be using onPaint method but this is the requirements of the task

Thanks

public Square(Point keyPt, Point oppPt)   // constructor
    {
        this.keyPt = keyPt;
        this.oppPt = oppPt;
    }

    // You will need a different draw method for each kind of shape. Note the square is drawn
    // from first principles. All other shapes should similarly be drawn from first principles. 
    // Ideally no C# standard library class or method should be used to create, draw or transform a shape
    // and instead should utilse user-developed code.
    public void draw(Graphics g, Pen blackPen)
    {
        // This method draws the square by calculating the positions of the other 2 corners
        double xDiff, yDiff, xMid, yMid;   // range and mid points of x & y  

        // calculate ranges and mid points
        xDiff = oppPt.X - keyPt.X;
        yDiff = oppPt.Y - keyPt.Y;
        xMid = (oppPt.X + keyPt.X) / 2;
        yMid = (oppPt.Y + keyPt.Y) / 2;

        // draw square
        g.DrawLine(blackPen, (int)keyPt.X, (int)keyPt.Y, (int)(xMid + yDiff / 2), (int)(yMid - xDiff / 2));
        g.DrawLine(blackPen, (int)(xMid + yDiff / 2), (int)(yMid - xDiff / 2), (int)oppPt.X, (int)oppPt.Y);
        g.DrawLine(blackPen, (int)oppPt.X, (int)oppPt.Y, (int)(xMid - yDiff / 2), (int)(yMid + xDiff / 2));
        g.DrawLine(blackPen, (int)(xMid - yDiff / 2), (int)(yMid + xDiff / 2), (int)keyPt.X, (int)keyPt.Y);
    }

    public void fillSquare(Graphics g, Brush redBrush)
    {
        float xDiff = oppPt.X - keyPt.X;
        float yDiff = oppPt.Y - keyPt.Y;
        float xMid = (oppPt.X + keyPt.X) / 2;
        float yMid = (oppPt.Y + keyPt.Y) / 2;

        var path = new GraphicsPath();
        path.AddLines(new PointF[] {
        keyPt,
        new PointF(xMid + yDiff/2, yMid-xDiff/2),
        oppPt
        });

        path.AddLines(new PointF[] {
        keyPt,
        new PointF(xMid - yDiff/2, yMid + xDiff/2),
        oppPt
        });

        path.CloseFigure();

        // Fill Triangle
        g.FillPath(redBrush, path);

    }
}

}

i have tried this method but something is missing i don't know what is it

private void itemRotation(PaintEventArgs e)
    {
        Pen blackpen = new Pen(Color.Black);
        Graphics g = e.Graphics;
        Font myFont = new System.Drawing.Font("Helvetica", 9);
        Brush blackwriter = new SolidBrush(System.Drawing.Color.Black);


        if (rotateItem)
        {
            for (int i = 0; i < shapes.Count; i++)
            {
                if (shapes[i].Selected)
                {
                    if (shapes[i].ShapeType == (int)ShapeTypes.Square)
                    {
                        PointF center = new PointF(shapes[i].keyPt.X + (shapes[i].oppPt.X / 2.0F), shapes[i].keyPt.Y + (shapes[i].oppPt.Y / 2.0F));
                        shapes[i].keyPt = new Point(shapes[i].keyPt.X, shapes[i].keyPt.Y);
                        shapes[i].oppPt = new Point(shapes[i].oppPt.X, shapes[i].oppPt.Y);
                        Matrix myMatrix = new Matrix();
                        myMatrix.Rotate(30);
                        g.Transform = myMatrix;
                        ((Square)shapes[i]).draw(g, blackpen);
                        g.DrawString("2nd pos", myFont, blackwriter, shapes[i].keyPt.X, shapes[i].oppPt.X);
                    }
                }
            }
        }
    }

Solution

  • Below is an example of how to draw the same shape (a GraphicsPath) into various locations and rotations.

    The key here is the following two commands

    e.Graphics.TranslateTransform(x, y);
    e.Graphics.RotateTransform(-angle);
    

    See results below:

    screenshot

    and the code used to generate it:

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        // This code defines a graphics shape using a GraphicsPath
        // and draws multiple copies along a grid and with various
        // rotation angle angles.
        e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
        var target = sender as PictureBox;
    
        // Step 1 - Define a rectangle 20 by 12 pixels, center at origin.
        var gp = new GraphicsPath();
        gp.AddLines(new PointF[] {
            new PointF(-10, -6),
            new PointF( 10, -6),
            new PointF( 10,  6),
            new PointF(-10,  6) });
        gp.CloseFigure();
    
        // Step 2 - Define a 10×9 grid with two loops
        float angle = 0;
        for (int i = 0; i<9; i++)
        {
            // divide the control height into 10 divisions
            float y = (i+1)*target.Height/10;
            for (int j = 0; j<10; j++)
            {
                // divide the control width into 11 divisions
                float x = (j+1)*target.Width/11;
                // Save the default transformation state
                var state = e.Graphics.Save();
    
                // Traslate the origin to (x,y), each grid point
                e.Graphics.TranslateTransform(x, y);
                // Rotate shape by an angle (negative = CCW)
                e.Graphics.RotateTransform(-angle);
    
                // Draw the shape
                e.Graphics.FillPath(Brushes.LightSeaGreen, gp);
                e.Graphics.DrawPath(Pens.Black, gp);
    
                // Restore the default transformation state
                e.Graphics.Restore(state);
    
                // Increment the angle by one degree. 
                // The idea is to show all 90 degrees of rotation in a 10×9 grid.
                angle++;
            }
        }
    }