如何在 C# 中旋转二维对象

Posted

技术标签:

【中文标题】如何在 C# 中旋转二维对象【英文标题】:How to rotate 2d object in C# 【发布时间】:2019-08-15 01:56:59 【问题描述】:

基本上我有一个窗口窗体,用户将能够绘制不同的形状(例如正方形、圆形和三角形),用户将能够在绘制后突出显示这些形状中的任何一个,然后通过移动或旋转来控制突出显示的形状,我不知道如何旋转形状。任何人都可以提供帮助,这是我的代码(仅用于绘制正方形) PS:用户需要在表格上单击两次才能在这两个点之间绘制形状,如下所示我也知道我应该使用 onPaint 方法,但这是任务的要求

谢谢

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

    

我试过这个方法,但缺少一些东西我不知道它是什么

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

【问题讨论】:

通常的方法是使用Graphics.RotateTransform 和两个 TranslateTransform 调用将原点移动到旋转的中心点。 您不得破坏您的问题并在回答后删除其所有内容。在提出问题时,您不可撤销地将其内容授权给 Stack Overflow,只要他们给予您信任(使用您的用户名)即可分发。如果您对此政策有任何疑问,请contact the team。 【参考方案1】:

以下是如何将相同形状(GraphicsPath)绘制到不同位置和旋转的示例。

这里的关键是下面两个命令

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

查看以下结果:

以及用于生成它的代码:

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

【讨论】:

以上是关于如何在 C# 中旋转二维对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使游戏对象在旋转平面中围绕 Unity 中的另一个游戏对象旋转

Unity 2D C#如何在点击时制作面向对象的坐标

如何将 c# 二维数组转换为 JSON 对象?

如何在模板匹配中找到 ROI 内对象的旋转?

如何在 C# 中为 Matrix 类初始化二维数组

在 Python 中旋转二维数组