它已经到了点在我的程序,现在,我有5个摇摆摆,都是在一次修改滑块值。这些值被绘制到from上,并通过类钟摆传递。若要更改值,将运行update按钮,它们是使用工作的安装程序的默认选项。这些值也通过一些简单的标签显示在屏幕上。“零”按钮将所有值(长度除外)设置为零。
现在,我的下一个任务是使摆在“现实”的碰撞,并重新创造一个牛顿摇篮式的效果。我研究了粒子上的弹性碰撞解,例如,下面是一个很好的例子:球对球碰撞.检测和处理
我也看过它背后的原始物理,这里,但是我的大脑无法理解事物的原始物理方面。
所以我想知道是否有人能帮我找出碰撞的理论。
我目前的想法是,当坐标满足时,速度只会改变极性,例如,在对摆中的+10到-10。我说对了吗?
这是我的摆班:
class Pendulum
{
//all public static so they are actually global (can be used between classes and not just global to this class).
public static int length = 10;//length of arm /** can't be less than 0 or will break.
public static double angle = 0; //pendulums arm angle
public static double aAcc = 0.00; //Angle acceleration
public static double aVel = 0.00; //anglular velocity
public static double damping = 0.000; //friction //friction
public static double gravity = 0.0; //make gravity a constant
int originX = 0;
int originY = 0; //allways 0
int bobX; // = frmWidth / 2;
int bobY; // = (int)length; Drawn in pendulm as don't really need to be global. Are currently for flexibilty.
Timer timer; //global for flexibility
public Pendulum(int frmWidth, int frmHeight)
{
timer = new Timer() { Interval = 30 };
timer.Tick += delegate(object sender, EventArgs e)
{
//-----------------drawing variables------------------------------//
originX = frmWidth / 2;
originY = 0;
//to be relative to origin we go:
bobX = originX + (int)(Math.Sin(angle) * length);
bobY = originY + (int)(Math.Cos(angle) * length);
//gravity
aAcc = (-1 * gravity / length) * Math.Sin(angle); //calculate acceleration
aVel += aAcc;//increment velcocity
angle += aVel;//incrment angle
aVel *= damping;//friction action, pendulum eventually 0's
};
timer.Start();
}
public void DrawPendulum(Graphics g)
{
g.DrawLine(Pens.Black, originX, originY, bobX, bobY);
g.FillEllipse(Brushes.Red, bobX - 8, bobY, 20, 20); //-8 to make it look more central!
}
}这是表单代码:
public partial class frmPendulum : Form
{
private Timer timer;
private Pendulum p1 = null;
private Pendulum p2 = null;
private Pendulum p3 = null;
private Pendulum p4 = null;
private Pendulum p5 = null;
public frmPendulum()
{
InitializeComponent();
this.Shown += new EventHandler(frmPendulum_Shown);
this.Paint += new PaintEventHandler(frmPendulum_Paint);
}
void frmPendulum_Shown(object sender, EventArgs e)
{
p1 = new Pendulum(this.ClientRectangle.Width, this.ClientRectangle.Height);
p2 = new Pendulum(this.ClientRectangle.Width + 40, this.ClientRectangle.Height);
p3 = new Pendulum(this.ClientRectangle.Width - 40, this.ClientRectangle.Height);
p4 = new Pendulum(this.ClientRectangle.Width - 80, this.ClientRectangle.Height);
p5 = new Pendulum(this.ClientRectangle.Width + 80, this.ClientRectangle.Height);
timer = new Timer() { Interval = 100 };
timer.Tick += delegate(object s2, EventArgs e2)
{
this.Refresh();
Value.Text = string.Format("Length: " + Pendulum.length + "{0}Angle: " + Pendulum.angle + "{0}Acc: " + Pendulum.aAcc + "{0}Vel: " + Pendulum.aVel + "{0}Damping: " + Pendulum.damping + "{0}Gravity: " + Pendulum.gravity, Environment.NewLine);
value2.Text = string.Format("Length: " + tbrLength.Value + "{0}Angle: " + ((double)tbrAngle.Value) / 100.0 + "{0}Vel: " + ((double)tbrAVel.Value) / 100.0 + "{0}Damping: " + ((double)tbrDamp.Value) / 100.0 + "{0}Gravity: " + ((double)tbrGrav.Value) / 100.0, Environment.NewLine);
};
timer.Start();
}
void frmPendulum_Paint(object sender, PaintEventArgs e)
{
switch (tbrNoOfPend.Value)
{
case 1:
if (p1 != null) //if used because the Paint() event could occur BEFORE "p1"etc. has been instantiated.
{
p1.DrawPendulum(e.Graphics);
}
break;
case 2:
if (p2 != null)
{
p2.DrawPendulum(e.Graphics);
}
goto case 1;
case 3:
if (p3 != null)
{
p3.DrawPendulum(e.Graphics);
}
goto case 2;
case 4:
if (p4 != null)
{
p4.DrawPendulum(e.Graphics);
}
goto case 3;
case 5:
if (p5 != null)
{
p5.DrawPendulum(e.Graphics);
}
goto case 4;
default:
break;
}
}
private void btnDefault_Click(object sender, EventArgs e)
{
//sets values to a good calibration by default.
Pendulum.length = 50;
Pendulum.angle = Math.PI / 2; //pendulums arm angle
Pendulum.aAcc = 0.00; //Angle acceleration
Pendulum.aVel = 0.00; //anglular velocity
Pendulum.damping = 0.995; //friction //friction
Pendulum.gravity = 0.4; //make gravity a constant
UpdateSliders();
}
private void UpdateValues()
{
/** The trackbars only use integer values so to increment in decimals certain values have to be divided by 100 so they are correct in the simulation.
* For example is I want the gravity to be 0.4 my track bars value will have to be 40 / 100 = 0.40
* Another example will be angle that will go from -3 to 3 incrementing in decimals we go from -300 to 300 /100 = 3 **/
Pendulum.length = tbrLength.Value; //length is ok as it is an integer
Pendulum.angle = ((double)tbrAngle.Value) / 100.0; //both numerator and denominator must be of the same type.
// acceleration is calculated so isn't sent
Pendulum.aVel = ((double)tbrAVel.Value) / 100.0;
Pendulum.damping = ((double)tbrDamp.Value) / 100.0;
Pendulum.gravity = ((double)tbrGrav.Value) / 100.0;
}
private void UpdateSliders()
{
tbrLength.Value = Pendulum.length;
tbrAngle.Value = (int)(Pendulum.angle * 100.0); //pendulums arm angle
//tbrAAcc.Value = (int) Pendulum.aAcc; //Removed acceleration as it is re-calculated anyway.
tbrAVel.Value = (int)(Pendulum.aVel* 100.0); //anglular velocity
tbrDamp.Value = (int)(Pendulum.damping * 100.0); //friction //friction
tbrGrav.Value = (int)(Pendulum.gravity * 100.0); //make gravity a constant
}
private void btnUpdateValues_Click(object sender, EventArgs e)
{
UpdateValues();
//this.Shown += new EventHandler(frmPendulum_Shown);
//this.Paint += new PaintEventHandler(frmPendulum_Paint);
}
private void button1_Click(object sender, EventArgs e)
{
//zero's everything except length.
Pendulum.angle = 0; //pendulums arm angle
Pendulum.aAcc = 0.00; //Angle acceleration
Pendulum.aVel = 0.00; //anglular velocity
Pendulum.damping = 0; //friction //friction
Pendulum.gravity = 0; //make gravity a constant
UpdateSliders();
}
}发布于 2013-10-29 04:51:24
好的,看来代码方面的事情,你可以自己搞清楚,老实说,我真的不是c#专家,但我会尝试处理这方面的物理方面。
牛顿摇篮的酷之处在于,无论两端之间有多少个球,能量都是保守的,或者至少是近似守恒的。在你走得更远之前,你需要决定你希望这样做有多现实。我们都知道,一个真正的牛顿摇篮不会永远摇摆,但是确定在每次碰撞中损失多少能量是一个非常复杂的物理问题。
如果你想确定在每次碰撞中损失了多少能量,你就需要这么多额外的细节,然后需要通过实际测量摆高和诸如此类的东西来进行实验计算。
从这里开始,我将假设你们谈论的是完全弹性碰撞,其中能量和动量都是守恒的。
在处理弹性碰撞时,有几件事你需要知道:
M1*V1 = M2*V2 according to momentum; M is mass, V is velocity
E_kinetic = 1/2*m*v^2
E_potential = mgh where m = mass, g = acceleration due to gravity, and h = height关于一些钟摆理论:
当你把一个钟摆拉回来的时候,你把它拉回某个角度θ,但是这个角度只对决定你在y方向上升到多高的钟摆很重要。钟摆的长度非常重要,就像支撑质量的绳子的长度一样。一旦你知道你把钟摆举得有多高,用θ来计算,或者仅仅知道y的位移,你就可以计算摆在摆动底部的速度,在牛顿的摇篮里,钟摆会接触到下一个球。
为了用θ来计算摆的高度,你把摆的长度乘以θ的余弦,然后从摆长中减去它。或者数学方面:
l = length of pendulum
theta = angle of the pulled back pendulum relative to the vertical axis
h = height
now actual calculations:
h = l - l*cos(theta)有了这个h,我们现在可以用以前的能量公式来确定摆在路径底部的速度。
由于能量在这个系统中是守恒的,当我们把球拉回来的时候,球是静止的,我们知道它的最大势能在它的拉回路径的顶端,当我们把它拉回来时,它没有任何动能,因为它的速度是零。
KE = PE
PE = m * g * h
KE = 1/2 * m * v^2
m * g * h = 1/2 * m * v^2
v cancels
g * h = 1/2 * v^2
v = sqrt(2 * g * h)
(g = 9.8 m/s^2 or 32 f/s^2)既然你有了v,你就可以弄清楚其他不同质量的振动对你的第一个振动会有什么反应。
对于这个程序来说,无聊的是摆中的中间球,如果你假设有弹性碰撞,那就无关紧要了。
另外,摇篮另一端的钟摆会摆动到你把第一个钟摆拉到的高度。虽然在现实中会有一些能量损失。如果你想以一种有点作弊的方式计算出多少能量损失了,你可以看看一个婴儿摇篮在停止移动之前会点击多少次。
假设系统以100焦耳的能量开始,在它们停止移动之前,球要碰撞100次,你知道,每次碰撞你都会损失大约1焦耳的能量。启动能量的系统可以使用任何一种能量公式来计算,尽管你必须记住要把质量加回去。
一旦你知道每一次碰撞都损失了多少能量,你就把这些公式倒过来,看看另一边会上升到多高。
Calculate the kinetic energy
subtract your calculated loss
plug into the potential energy formula
determine the height from the potential energy formulahttps://stackoverflow.com/questions/19368017
复制相似问题