尝试在Windows窗体中创建基本的两缸发动机横截面动画,但无法使曲柄圆居中

问题描述 投票:0回答:1

我一直在尝试以窗口形式为两缸发动机创建基本发动机横截面,每个活塞的动画和角度都正确,但曲柄不在两个活塞之间居中。

The two pistons and as you can see the crank is incorrectly placed

这似乎是一个非常简单的问题,我已经检查了我的代码行并确保所有变量和计算都是正确的,我相信活塞角度的转换导致了这个问题,但不明白为什么。

我在每个气缸之前使用的变换如下,并且在每个活塞绘图之间重置旋转变换:

g.TranslateTransform(CentreScene.X, CentreScene.Y);
g.RotateTransform(TiltAngle);
g.TranslateTransform(-CentreScene.X, -CentreScene.Y);

完整的绘图代码在这里:(请注意,它效率不高,而且有点混乱,但这只是一个概念证明,我将在它工作后进行完善)

    public void SBR_DrawCrossSection(Graphics g)
    {
        if (DesignMode || MainForm == null || MainForm.ACCESSOR_GrabEngineObject == null)
        {
            return; // Skip the method entirely if in design mode or objects are null
        }

        // Storing common use engine object values in variables
        int RodLength = Convert.ToInt16(MainForm.ACCESSOR_GrabEngineObject.ACCESSOR_ATTRB_RodLength) * 2;
        int CompressionHight = Convert.ToInt16(MainForm.ACCESSOR_GrabEngineObject.ACCESSOR_ATTRB_CompressionHight) * 2;
        int CrankRadius = Convert.ToInt16(MainForm.ACCESSOR_GrabEngineObject.ACCESSOR_ATTRB_CrankRadius);
        int PistonDiameter1 = Convert.ToInt16(MainForm.ACCESSOR_GrabEngineObject.ACCESSOR_ATTRB_BoreDiameter) * 7; // First piston bore
        int PistonDiameter2 = Convert.ToInt16(MainForm.ACCESSOR_GrabEngineObject.ACCESSOR_ATTRB_BoreDiameter) * 7; // Second piston bore
        int BoreHight = Convert.ToInt16(MainForm.ACCESSOR_GrabEngineObject.ACCESSOR_ATTRB_BoreHight) * 2;
        int RodCrankConnectionCircleRadius = 5;
        int TotalPistonHeight = RodLength + CompressionHight;

        // Rotates the crank by the crank shaft speed
        CrankShaftRotationAngle += CrankShaftSpeed;

        if (CrankShaftRotationAngle >= 360) { CrankShaftRotationAngle = 0; } // Resets the crank shaft rotation angle when it passes 360

        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

        // Creates a new point at the centre of the scene
        Point CentreScene = new Point((int)(g.VisibleClipBounds.Width / (double)2), (int)(g.VisibleClipBounds.Height / (double)2));

        // Creates a new point offset from the centre point by the complete height of the piston and the crank radius
        Point CrankShaftCentre = new Point(CentreScene.X, CentreScene.Y + RodLength + CompressionHight);

        g.TranslateTransform(CentreScene.X, CentreScene.Y);
        g.RotateTransform(TiltAngle); // Use first piston tilt angle
        g.TranslateTransform(-CentreScene.X, -CentreScene.Y);

        // Draw the crank shaft
        g.FillEllipse(Brushes.Gray, CrankShaftCentre.X - CrankRadius, CrankShaftCentre.Y - CrankRadius, CrankRadius * 2, CrankRadius * 2);

        // Calculate position of the crank and rod connection circle for the first piston
        Point RodCrankConnectionCircle1 = new Point((int)(CentreScene.X + Math.Cos(CrankShaftRotationAngle * Math.PI / 180) * 0.5 * CrankRadius),
            ((int)(CentreScene.Y + Math.Sin(CrankShaftRotationAngle * Math.PI / 180) * 0.5 * CrankRadius)) + RodLength + CompressionHight);

        // Draw the connection circle for the first piston on the crank shaft
        g.FillEllipse(Brushes.WhiteSmoke, RodCrankConnectionCircle1.X - RodCrankConnectionCircleRadius, RodCrankConnectionCircle1.Y - RodCrankConnectionCircleRadius,
            RodCrankConnectionCircleRadius * 2, RodCrankConnectionCircleRadius * 2);

        // Calculating the position of the first piston head's base
        Point PistonHeadBottom1 = new Point(CentreScene.X, (int)(CentreScene.Y - (CrankRadius * 1.5) - (CrankShaftCentre.Y - RodCrankConnectionCircle1.Y)));

        // Draw the line representing the rod from the crank connection circle to piston base
        using (Pen Pen = new Pen(Brushes.OrangeRed, 3)) { g.DrawLine(Pen, RodCrankConnectionCircle1, PistonHeadBottom1); }

        // Create a new point at the top of the first piston head
        Point PistonTop1 = new Point((int)(PistonHeadBottom1.X - PistonDiameter1 / (double)2), PistonHeadBottom1.Y - TotalPistonHeight);

        // Draw the first piston head
        g.FillRectangle(Brushes.OrangeRed, PistonTop1.X, PistonTop1.Y, PistonDiameter1, TotalPistonHeight);

        Point LeftCylinderWall1 = new Point(PistonTop1.X, CentreScene.Y - TotalPistonHeight - 75);
        Point RightCylinderWall1 = new Point(PistonTop1.X + PistonDiameter1, CentreScene.Y - TotalPistonHeight - 75);

        using (Pen Pen = new Pen(Brushes.Yellow, 3))
        {
            // Draw the cylinder walls for the first piston
            g.DrawLine(Pen, LeftCylinderWall1.X, LeftCylinderWall1.Y, LeftCylinderWall1.X, LeftCylinderWall1.Y + BoreHight + 50);
            g.DrawLine(Pen, RightCylinderWall1.X, RightCylinderWall1.Y, RightCylinderWall1.X, RightCylinderWall1.Y + BoreHight + 50);
            // Draw the top connecting line for the first piston
            g.DrawLine(Pen, LeftCylinderWall1, RightCylinderWall1);

        }

        g.ResetTransform();
        g.TranslateTransform(CentreScene.X, CentreScene.Y);
        g.RotateTransform(315); // Use first piston tilt angle
        g.TranslateTransform(-CentreScene.X, -CentreScene.Y);

        // Calculate the position of the second piston (180 degrees out of phase)
        double CrankShaftRotationAngle2 = CrankShaftRotationAngle + 180; // Phase shift by 180 degrees
        Point RodCrankConnectionCircle2 = new Point((int)(CentreScene.X + Math.Cos(CrankShaftRotationAngle2 * Math.PI / 180) * 0.5 * CrankRadius),
            ((int)(CentreScene.Y + Math.Sin(CrankShaftRotationAngle2 * Math.PI / 180) * 0.5 * CrankRadius)) + RodLength + CompressionHight);

        // Draw the connection circle for the second piston on the crank shaft
        g.FillEllipse(Brushes.WhiteSmoke, RodCrankConnectionCircle2.X - RodCrankConnectionCircleRadius, RodCrankConnectionCircle2.Y - RodCrankConnectionCircleRadius,
            RodCrankConnectionCircleRadius * 2, RodCrankConnectionCircleRadius * 2);

        // Calculating the position of the second piston head's base
        Point PistonHeadBottom2 = new Point(CentreScene.X, (int)(CentreScene.Y - (CrankRadius * 1.5) - (CrankShaftCentre.Y - RodCrankConnectionCircle2.Y)));

        // Draw the line representing the rod from the crank connection circle to second piston base
        using (Pen Pen = new Pen(Brushes.OrangeRed, 3)) { g.DrawLine(Pen, RodCrankConnectionCircle2, PistonHeadBottom2); }

        // Create a new point at the top of the second piston head
        Point PistonTop2 = new Point((int)(PistonHeadBottom2.X - PistonDiameter2 / (double)2), PistonHeadBottom2.Y - TotalPistonHeight);

        // Draw the second piston head
        g.FillRectangle(Brushes.OrangeRed, PistonTop2.X, PistonTop2.Y, PistonDiameter2, TotalPistonHeight);

        // Draw the cylinder walls and top for second piston
        Point LeftCylinderWall2 = new Point(PistonTop2.X, CentreScene.Y - TotalPistonHeight - 75);
        Point RightCylinderWall2 = new Point(PistonTop2.X + PistonDiameter2, CentreScene.Y - TotalPistonHeight - 75);

        using (Pen Pen = new Pen(Brushes.Yellow, 3))
        {

            // Draw the cylinder walls for the second piston
            g.DrawLine(Pen, LeftCylinderWall2.X, LeftCylinderWall2.Y, LeftCylinderWall2.X, LeftCylinderWall2.Y + BoreHight + 50);
            g.DrawLine(Pen, RightCylinderWall2.X, RightCylinderWall2.Y, RightCylinderWall2.X, RightCylinderWall2.Y + BoreHight + 50);
            // Draw the top connecting line for the second piston
            g.DrawLine(Pen, LeftCylinderWall2, RightCylinderWall2);
        }

        // Reset the transformation to prevent affecting other drawings
        g.ResetTransform();
    }
c# winforms animation
1个回答
0
投票

通过确保 y 方向上的变换解决了中心灰色圆圈在 y 方向上的偏移,成功解决了这个问题:

           g.TranslateTransform(CentreScene.X, CentreScene.Y + RodLength + CompressionHight);
           g.RotateTransform(315); // Use first piston tilt angle
           g.TranslateTransform(-CentreScene.X, -CentreScene.Y - RodLength - CompressionHight);
© www.soinside.com 2019 - 2024. All rights reserved.