def collision_response_cotin(pair, liver, past_p, current_p):
    move_v_disp_dict = {}
    move_tri_indexs = []
    flat_list = [item for sublist in list(pair.values()) for item in sublist]
    p_indexs = np.array(flat_list).reshape((- 1))
    p_n = p_indexs.shape[0]
    ray = (current_p[p_indexs] - past_p[p_indexs])
    ray = (ray * (1 / np.linalg.norm(ray, axis=(- 1)))[:, None])
    dn = (example @ example.com.T)
    ap = (liver.x[liver.tri_elements[:, 0]][None, :] - past_p[p_indexs][:, None])
    apn = (ap * liver.tri_normal_vec[None, :]).sum(axis=(- 1))
    ts = (apn * (1 / dn))
    int_p = ((ts[:, :, None] * ray[:, None]) + past_p[p_indexs][:, None])
    v1 = (liver.x[liver.tri_elements[:, 1]] - liver.x[liver.tri_elements[:, 0]])
    v2 = (liver.x[liver.tri_elements[:, 2]] - liver.x[liver.tri_elements[:, 0]])
    tri_areax2 = np.linalg.norm(np.cross(v1, v2, axis=(- 1)), axis=(- 1))
    bc_temp = np.zeros((p_n, liver.n_tri, 3, 3, 3))
    bc_temp[:] = np.tile(liver.x[liver.tri_elements], 3).reshape((- 1), 3, 3, 3).transpose(0, 2, 1, 3)
    for itemp in range(p_n):
        bc_temp[itemp, :, [0, 1, 2], [0, 1, 2]] = int_p[itemp]
    v1 = (bc_temp[:, :, :, 1] - bc_temp[:, :, :, 0])
    v2 = (bc_temp[:, :, :, 2] - bc_temp[:, :, :, 0])
    areax2 = np.linalg.norm(np.cross(v1, v2, axis=(- 1)), axis=(- 1))
    bc_co = (areax2 * (1.0 / tri_areax2)[np.newaxis, :, np.newaxis])
    for itemp in range(p_n):
        check1 = np.argwhere((abs((bc_co[itemp].sum(axis=(- 1)) - 1)) < 0.001)).flatten()
        check2 = np.argwhere((dn[itemp] < 0)).flatten()
        psb_tri_index = np.intersect1d(check1, check2)
        if (psb_tri_index.size != 0):
            psb_ts = ts[(itemp, psb_tri_index)]
            move_tri_index = psb_tri_index[psb_ts.argmin()]
            move_t = (current_p[p_indexs[itemp]] - int_p[(itemp, move_tri_index)])
            move_v_index_p = liver.tri_elements[move_tri_index]
            for ividx in move_v_index_p:
                if (ividx not in move_v_disp_dict.keys()):
                    move_v_disp_dict[ividx] = move_t
                elif (np.linalg.norm(np.c_[(move_v_disp_dict[ividx], move_t)].T, axis=(- 1)).argmax() == 1):
                    move_v_disp_dict[ividx] = move_t
            move_tri_indexs.append(move_tri_index.tolist())
    print(move_tri_indexs)
    return move_v_disp_dict
def collision_response_cotin(pair, liver, past_p, current_p):
    move_v_disp_dict = {}
    move_tri_indexs = []
    flat_list = [item for sublist in list(pair.values()) for item in sublist]
    p_indexs = np.array(flat_list).reshape((- 1))
    p_n = p_indexs.shape[0]
    ray = (current_p[p_indexs] - past_p[p_indexs])
    ray = (ray * (1 / np.linalg.norm(ray, axis=(- 1)))[:, None])
    dn = (example @ example.com.T)
    ap = (liver.x[liver.tri_elements[:, 0]][None, :] - past_p[p_indexs][:, None])
    apn = (ap * liver.tri_normal_vec[None, :]).sum(axis=(- 1))
    ts = (apn * (1 / dn))
    int_p = ((ts[:, :, None] * ray[:, None]) + past_p[p_indexs][:, None])
    v1 = (liver.x[liver.tri_elements[:, 1]] - liver.x[liver.tri_elements[:, 0]])
    v2 = (liver.x[liver.tri_elements[:, 2]] - liver.x[liver.tri_elements[:, 0]])
    tri_areax2 = np.linalg.norm(np.cross(v1, v2, axis=(- 1)), axis=(- 1))
    bc_temp = np.zeros((p_n, liver.n_tri, 3, 3, 3))
    bc_temp[:] = np.tile(liver.x[liver.tri_elements], 3).reshape((- 1), 3, 3, 3).transpose(0, 2, 1, 3)
    for itemp in range(p_n):
        bc_temp[itemp, :, [0, 1, 2], [0, 1, 2]] = int_p[itemp]
    v1 = (bc_temp[:, :, :, 1] - bc_temp[:, :, :, 0])
    v2 = (bc_temp[:, :, :, 2] - bc_temp[:, :, :, 0])
    areax2 = np.linalg.norm(np.cross(v1, v2, axis=(- 1)), axis=(- 1))
    bc_co = (areax2 * (1.0 / tri_areax2)[np.newaxis, :, np.newaxis])
    for itemp in range(p_n):
        check1 = np.argwhere((abs((bc_co[itemp].sum(axis=(- 1)) - 1)) < 0.001)).flatten()
        check2 = np.argwhere((dn[itemp] < 0)).flatten()
        psb_tri_index = np.intersect1d(check1, check2)
        if (psb_tri_index.size != 0):
            psb_ts = ts[(itemp, psb_tri_index)]
            move_tri_index = psb_tri_index[psb_ts.argmin()]
            move_t = (current_p[p_indexs[itemp]] - int_p[(itemp, move_tri_index)])
            move_v_index_p = liver.tri_elements[move_tri_index]
            for ividx in move_v_index_p:
                if (ividx not in move_v_disp_dict.keys()):
                    move_v_disp_dict[ividx] = move_t
                elif (np.linalg.norm(np.c_[(move_v_disp_dict[ividx], move_t)].T, axis=(- 1)).argmax() == 1):
                    move_v_disp_dict[ividx] = move_t
            move_tri_indexs.append(move_tri_index.tolist())
    print(move_tri_indexs)
    return move_v_disp_dict