оп попросил время столкновения. Немного другой подход вычислит это точно ...
Помните, что уравнение проекции положения:
NEW_POS=POS+VEL*t+(ACC*t^2)/2
Если мы заменим POS
на D_POS=POS_A-POS_B
, VEL
на D_VEL=VEL_A-VEL_B
и ACC=ACC_A-ACC_B
для объектов A
и B
, мы получим:
$D_NEW_POS=D_POS+D_VEL*t+(D_ACC*t^2)/2
Это формула для векторного расстояния между объектами. Чтобы получить квадрат скалярного расстояния между ними, мы можем взять квадрат этого уравнения, который после расширения выглядит следующим образом:
distsq(t) = D_POS^2+2*dot(D_POS,D_VEL)*t + (dot(D_POS, D_ACC)+D_VEL^2)*t^2 + dot(D_VEL,D_ACC)*t^3 + D_ACC^2*t^4/4
Чтобы найти время, когда происходит столкновение, мы можем установить уравнение равным квадрату суммы радиусов и решить для t
:
0 = D_POS^2-(r_A+r_B)^2 + 2*dot(D_POS,D_VEL)*t + (dot(D_POS, D_ACC)+D_VEL^2)*t^2 + dot(D_VEL,D_ACC)*t^3 + D_ACC^2*t^4/4
Теперь мы можем найти уравнение, используя формулу четвертого порядка .
Формула квартики даст 4 корня, но нас интересуют только вещественные корни. Если существует двойной реальный корень, то два объекта касаются краев ровно в один момент времени. Если существует два реальных корня, то объекты непрерывно перекрываются между корнем 1 и корнем 2 (то есть корень 1 - это время, когда начинается столкновение, а корень 2 - это время, когда прекращается столкновение). Четыре реальных корня означают, что объекты сталкиваются дважды, непрерывно между парами корней 1,2 и 3,4.
В R я использовал polyroot()
для решения следующим образом:
# initial positions
POS_A=matrix(c(0,0),2,1)
POS_B=matrix(c(2,0),2,1)
# initial velocities
VEL_A=matrix(c(sqrt(2)/2,sqrt(2)/2),2,1)
VEL_B=matrix(c(-sqrt(2)/2,sqrt(2)/2),2,1)
# acceleration
ACC_A=matrix(c(sqrt(2)/2,sqrt(2)/2),2,1)
ACC_B=matrix(c(0,0),2,1)
# radii
r_A=.25
r_B=.25
# deltas
D_POS=POS_B-POS_A
D_VEL=VEL_B-VEL_A
D_ACC=ACC_B-ACC_A
# quartic coefficients
z=c(t(D_POS)%*%D_POS-r*r, 2*t(D_POS)%*%D_VEL, t(D_VEL)%*%D_VEL+t(D_POS)%*%D_ACC, t(D_ACC)%*%D_VEL, .25*(t(D_ACC)%*%D_ACC))
# get roots
roots=polyroot(z)
# In this case there are only two real roots...
root1=as.numeric(roots[1])
root2=as.numeric(roots[2])
# trajectory over time
pos=function(p,v,a,t){
T=t(matrix(t,length(t),2))
return(t(matrix(p,2,length(t))+matrix(v,2,length(t))*T+.5*matrix(a,2,length(t))*T*T))
}
# plot A in red and B in blue
t=seq(0,2,by=.1) # from 0 to 2 seconds.
a1=pos(POS_A,VEL_A,ACC_A,t)
a2=pos(POS_B,VEL_B,ACC_B,t)
plot(a1,type='o',col='red')
lines(a2,type='o',col='blue')
# points of a circle with center 'p' and radius 'r'
circle=function(p,r,s=36){
e=matrix(0,s+1,2)
for(i in 1:s){
e[i,1]=cos(2*pi*(1/s)*i)*r+p[1]
e[i,2]=sin(2*pi*(1/s)*i)*r+p[2]
}
e[s+1,]=e[1,]
return(e)
}
# plot circles with radius r_A and r_B at time of collision start in black
lines(circle(pos(POS_A,VEL_A,ACC_A,root1),r_A))
lines(circle(pos(POS_B,VEL_B,ACC_B,root1),r_B))
# plot circles with radius r_A and r_B at time of collision stop in gray
lines(circle(pos(POS_A,VEL_A,ACC_A,root2),r_A),col='gray')
lines(circle(pos(POS_B,VEL_B,ACC_B,root2),r_B),col='gray')
Объект A
следует красной траектории от нижнего левого до верхнего правого. Объект B
следует по синей траектории от нижнего правого до верхнего левого. Два объекта непрерывно сталкиваются между временем 0,9194381 и временем 1,167549. Два черных круга просто касаются друг друга, показывая начало наложения - и наложение продолжается во времени, пока объекты не достигнут расположения серых кругов.