我一直在尝试以窗口形式为两缸发动机创建基本发动机横截面,每个活塞的动画和角度都正确,但曲柄不在两个活塞之间居中。
这似乎是一个非常简单的问题,我已经检查了我的代码行并确保所有变量和计算都是正确的,我相信活塞角度的转换导致了这个问题,但不明白为什么。
我在每个气缸之前使用的变换如下,并且在每个活塞绘图之间重置旋转变换:
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();
}
通过确保 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);