[docs]classBallBallCollisionStrategy(_BaseStrategy,Protocol):"""Ball-ball collision models must satisfy this protocol"""
[docs]defsolve(self,ball1:Ball,ball2:Ball)->Tuple[Ball,Ball]:"""This method resolves a ball-ball collision"""...
classCoreBallBallCollision(ABC):"""Operations used by every ball-ball collision resolver"""defmake_kiss(self,ball1:Ball,ball2:Ball)->Tuple[Ball,Ball]:"""Translate the balls so they are (almost) touching This makes a correction such that if the balls are not _exactly_ 2*R apart, they are moved equally along their line of centers such that they are. Then, to avoid downstream float precision round-off errors, a small epsilon of additional distance (constants.EPS_SPACE) is put between them, ensuring the balls are non-intersecting. """r1,r2=ball1.state.rvw[0],ball2.state.rvw[0]n=ptmath.unit_vector(r2-r1)correction=2*ball1.params.R-ptmath.norm3d(r2-r1)+const.EPS_SPACEball2.state.rvw[0]+=correction/2*nball1.state.rvw[0]-=correction/2*nreturnball1,ball2defresolve(self,ball1:Ball,ball2:Ball,inplace:bool=False)->Tuple[Ball,Ball]:ifnotinplace:ball1=ball1.copy()ball2=ball2.copy()ball1,ball2=self.make_kiss(ball1,ball2)returnself.solve(ball1,ball2)@abstractmethoddefsolve(self,ball1:Ball,ball2:Ball)->Tuple[Ball,Ball]:pass