def beam_overlap(beam_1, beam_2, t_dict, tol = 0.0001):
    """Returns parametric coefficients for line2 ends relative to line_1
    line_1 & line_2 are tuples of tuples (2D), each with trailing IDs
    for beam and point. 

    t_dict must contain entries t21 & t22 which are the parametric
    locations of ends 1 and 2 of beam 2 relative to beam 1. Note that the 
    dictionary can be generated by `eng_utilities.line_overlap`.

    Args:
        tol (float): a relative tolerance for the parameter t
    """
    (*_, ptID_11), (*_, ptID_12), beamID_1 = beam_1
    (*_, ptID_21), (*_, ptID_22), beamID_2 = beam_2

    t21, t22 = [t_dict.get(k, None) for k in ('t21', 't22')]
    new_beam_list = []

    # If parameters are missing from the dictionary
    if (t21 is None) or (t22 is None): # no change
        return [(beamID_1, ptID_11, ptID_12), (beamID_2, ptID_21, ptID_22)]
    # If both ends of both beams are essentially the same, return beam 1 only
    elif (-tol < t21 < tol) and ((1 - tol) < t22 < (1 + tol)):
        return [(beamID_1, ptID_11, ptID_12)]
    # If both ends of both beams are essentially the same but anti-parallel, return beam 1 only
    elif (-tol < t22 < tol) and ((1 - tol) < t21 < (1 + tol)):
        return [(beamID_1, ptID_11, ptID_12)]
    # If start ends of both beams are close, and beams are parallel, t22 > 1
    elif (-tol < t21 < tol) and (t22 > 1):
        return [(beamID_2, ptID_11, ptID_12), 
                (beamID_1, ptID_12, ptID_22),]
    # If start ends of both beams are close, and beams are parallel, t22 < 1
    elif (-tol < t21 < tol) and (t22 < 1):
        return [(beamID_1, ptID_11, ptID_21), 
                (beamID_2, ptID_21, ptID_22),]
    # If start and end ends of beams 1 & 2 are close, and beams are anti-parallel, t12 > 1
    elif (-tol < t22 < tol) and (t21 > 1):
        return [(beamID_2, ptID_11, ptID_12), 
                (beamID_1, ptID_12, ptID_21),]
    # If start and end ends of beams 1 & 2 are close, and beams are anti-parallel, t12 < 1
    elif (-tol < t22 < tol) and (t21 < 1):
        return [(beamID_1, ptID_11, ptID_22), 
                (beamID_2, ptID_22, ptID_21),]
    # line 1 encloses line 2
    elif ((0 < t21 < 1) and (0 < t22 < 1)):
        if t21 >= t22:
            return [(beamID_1, ptID_11, ptID_21),
                    (beamID_2, ptID_21, ptID_22),
                    (beamID_1, ptID_22, ptID_12),]
        else:
            return [(beamID_1, ptID_11, ptID_22),
                    (beamID_2, ptID_22, ptID_21),
                    (beamID_1, ptID_21, ptID_12),]
    # line 2 encloses line 1
    elif ((t21 < 0 and t22 > 0) or (t22 < 0 and t21 < 0)):
        if t21 >= t22:
            return [(beamID_2, ptID_21, ptID_11),
                    (beamID_1, ptID_11, ptID_12),
                    (beamID_2, ptID_12, ptID_22),]
        else:
            return [(beamID_2, ptID_22, ptID_11),
                    (beamID_1, ptID_11, ptID_12),
                    (beamID_2, ptID_12, ptID_21),]
    # parallel overlap, beam_1 first
    elif ((0 < t21 < 1) and (t22 > 1)):
        return [(beamID_1, ptID_11, ptID_21),
                (beamID_1, ptID_21, ptID_12),
                (beamID_2, ptID_12, ptID_22),]
    # parallel overlap, beam_2 first
    elif ((t21 < 0) and (0 < t22 < 1)):
        return [(beamID_2, ptID_21, ptID_11),
                (beamID_2, ptID_11, ptID_22),
                (beamID_1, ptID_22, ptID_12),]
    # anti-parallel overlap, beam_1 first
    elif ((0 < t22 < 1) and (t21 > 1)):
        return [(beamID_1, ptID_11, ptID_22),
                (beamID_1, ptID_22, ptID_12),
                (beamID_2, ptID_12, ptID_21),]
    # anti-parallel overlap, beam_1 first
    elif ((t22 < 0) and (0 < t21 < 1)):
        return [(beamID_2, ptID_22, ptID_11),
                (beamID_2, ptID_11, ptID_21),
                (beamID_1, ptID_21, ptID_12),]
    # Separate - no change
    elif ((t21 > 1 and t22 > 1) or (t21 < 1 and t22 < 1)): 
        return [(beamID_1, ptID_11, ptID_12), (beamID_2, ptID_21, ptID_22)]
    else: # catchall - no change
        return [(beamID_1, ptID_11, ptID_12), (beamID_2, ptID_21, ptID_22)]