本帖最后由 踢馆帝 于 2012-6-23 16:12 编辑
由于搬砖很辛苦,很久没出题了,终于放假了,先出一个吧
三维空间中有两个球,球心坐标分别是L1,L2。 ,半径是R1,R2。
现在两个球分别以速度V1,V2开始做直线运动(V1,V2也是三个分量的向量)
写一个小程序,给定(输入)L1,L2,R1,R2,V1,V2
基础题:判断两个球是否相撞。
扩展题:附加给定两个球的质量M1,M2。
如果相撞,求出相撞后两个球的速度V3,V4。
(假设这个空间没有任何阻力,摩擦,并且球碰撞是弹性碰撞,也就是碰撞不损失能量)
这里给出一组简单的数据,可供测试:(基础题)
L1 = (10,0,0)
L2 = (0,10,0)
V1 = (-1,0,0)
V2 = (0,-1,0)
得出的碰撞时刻是10-sqrt(2)
本帖最后由 LonghronShen 于 2012-6-22 22:41 编辑
都占坑了啊,那我也来一个
先做出基础题。
算法:
[查看全文]ImportsMicrosoft.Xna.FrameworkImportsSystem.Runtime.CompilerServicesModuleModuleMainPublic Class BallPublic Property Center() As Vector3Public Property R() As DoublePublic Property Mass() As DoublePublic ReadOnly Property IsLegal() As BooleanGetWith Me.CenterDim parts = {.X,.Y, .Z}For Each p In partsIf Single.IsInfinity(p)Or Single.IsNaN(p)ThenReturn FalseEnd IfNextEnd WithReturn Me.R <>0End GetEnd PropertyPublic Sub New()Me.Center =Vector3.ZeroMe.R = 0End SubPublic Sub New(ByVal p As Vector3, ByVal r As Double, ByVal m As Double)Me.Center = pMe.R = rMe.Mass = mEnd SubPublic Sub New(ByVal p As Vector4)Me.Center = New Vector3(p.X,p.Y, p.Z)Me.R = p.WEnd SubPublic Sub New(ByVal ParamArray p() As Double)If p.Length >= 4 ThenMe.Center = New Vector3(p(0), p(1), p(2))Me.R = p(3)If p.Length >=5 ThenMe.Mass =p(4)End IfElseThrow New ArgumentException("Too few arguments for Ball contructor.")End IfEnd SubEnd ClassPublic Function CreateVector4FromString(ByVal s As String, ByVal ParamArray sp() As String) As Vector4Dim parts = s.Split(sp,StringSplitOptions.RemoveEmptyEntries)If parts.Length >= 4 ThenReturn New Vector4(parts(0), parts(1), parts(2), parts(3))ElseThrow New ArgumentException("Wrong format for Vector4.")End IfEnd FunctionPublic Function CreateVector3FromString(ByVal s As String, ByVal ParamArray sp() As String) As Vector3Dim parts = s.Split(sp,StringSplitOptions.RemoveEmptyEntries)If parts.Length >= 3 ThenReturn New Vector3(parts(0), parts(1), parts(2))ElseThrow New ArgumentException("Wrong format for Vector3.")End IfEnd FunctionPublic Function Root(ByVal f As Func(Of Double, Double), ByVal f_ As Func(Of Double, Double), Optional ByVal x As Double = 0) As DoubleIf f(x) = 0 Then Return xDim stw As New Stopwatch()stw.Start()Dim x0 = xDox0 = xDim vf = f(x0)Dim vf_ = f_(x0)x = x - vf/ vf_Loop While Math.Abs((x - x0))>= 0.00001 Andstw.Elapsed.TotalSeconds < 20stw.Stop()If stw.Elapsed.TotalSeconds >20 ThenThrow New ArgumentException("Timeout when finding the root.")End IfReturn xEnd FunctionPublic Function GenericCast(Of U, V)(ByVal obj As U) As VTryReturn CType(DirectCast(obj, Object), V)Catch ex As InvalidCastExceptionReturn DirectCast(CompilerServices.Conversions.ChangeType(obj,GetType(V)), V)End TryEnd Function<Extension()>_Public Function OfType(Of U, V)(ByVal [Me] As IEnumerable(OfU)) As IEnumerable(OfV)Dim lst As New List(Of V)For Each item In [Me]lst.Add(GenericCast(OfU, V)(item))NextReturn lstEnd FunctionPublic Sub Pause()Console.WriteLine("Press any key to continue.")Console.ReadKey(True)End SubSub Main()While TrueTryConsole.WriteLine("Please input data for the first ball.")Console.WriteLine("x, y, z, r,[m]")Dim b1 = New Ball(Console.ReadLine().Split(",").OfType(Of Double)().ToArray())If b1.IsLegal =False ThenThrow New ArgumentException("The data for the first ball is illegal.")End IfConsole.WriteLine("Please input data for the second ball.")Console.WriteLine("x, y, z, r,[m]")Dim b2 = New Ball(Console.ReadLine().Split(",").OfType(Of Double)().ToArray())If b2.IsLegal =False ThenThrow New ArgumentException("The data forthe second ball is illegal.")End IfConsole.WriteLine("Please input the velocity for the first ball.")Console.WriteLine("Vector3: x, y,z")Dim v1 =CreateVector3FromString(Console.ReadLine(), ",")Console.WriteLine("Please input the velocity for the second ball.")Console.WriteLine("Vector3: x, y,z")Dim v2 = CreateVector3FromString(Console.ReadLine(),",")Dim dis =Function(t As Double)Return Vector3.Distance(New Vector3(b1.Center.X+ v1.X * t,b1.Center.Y + v1.Y * t,b1.Center.Z + v1.Z * t),New Vector3(b2.Center.X+ v2.X * t,b2.Center.Y + v2.Y * t,b2.Center.Z + v2.Z * t))End FunctionDim _dis =Function(t As Double)Dim g_ = Function(_t As Double)Return 2 * (Vector3.Distance(v1,v2) ^ 2) * _t +2 * ((b1.Center.X- b2.Center.X) * (v1.X - v2.X) +(b1.Center.Y- b2.Center.Y) * (v1.Y - v2.Y) +(b1.Center.Z- b2.Center.Z) * (v1.Z - v2.Z))End FunctionReturn 0.5 * Math.Pow(dis(t)^ 2, -0.5) * g_(t)End FunctionDim time = Root(dis,_dis)If dis(time)<= Math.Abs(b1.R + b2.R) ThenDim oldColor =Console.ForegroundColorConsole.ForegroundColor = ConsoleColor.RedConsole.WriteLine("The two balls will collide with each other.")Console.ForegroundColor = oldColorElseConsole.WriteLine("The two balls will not collide with eachother.")End IfCall Pause()Catch ex As ExceptionConsole.WriteLine(ex.Message& vbCrLf & ex.StackTrace.ToString())Call Pause()Console.Clear()Continue WhileEnd TryEnd WhileEnd SubEnd Module
本帖最后由 秋声赋 于 2012-6-22 00:38 编辑
没仔细检查
先放在这
就说思路 代码也没仔细看
先求相对速度和距离
因为没时间,所以规范化向量
以相对速度做一个坐标轴(原点在一个球的球心)
这时 2个球在该平面(相对速度向量过新坐标系原点的正交补)的投影就是2个圆了
然后就是求这两个球心在这个平面上的距离
想想下很容易看出 相对速度,相对距离,投影平面圆心的距离是一个三角形
求出投影平面的圆心距离
然后就是2D的判断圆是否相交
[mw_shl_code=csharp,true]
bool IsPeng=false;
Vector3D L1 = new Vector3D(1, 1, 1);
Vector3D L2 = new Vector3D(1, 1, 1);
double R1 = 1;
double R2 = 1;
Vector3D V1 = new Vector3D(1, 1, 1);
Vector3D V2 = new Vector3D(1, 1, 1);
Vector3D RV = V2 - V1;
Vector3D RX = L2 - L1;
RV.Normalize();
RX.Normalize();
if ((RX - RV).Length > (RX + RV).Length) return;
double RC = Math.Sqrt(RX.LengthSquared - RV.LengthSquared);
if (RC > R1 + R2) IsPeng = false;
else IsPeng = true;
[/mw_shl_code]
[查看全文]

