Fixes direction, connectivity and similar issues of the trim curves.

    This function works for surface trims in curve containers, i.e. trims consisting of multiple curves.

    Keyword Arguments:
        * ``tol``: tolerance value for comparing floats. *Default: 10e-8*
        * ``delta``: evaluation delta of the trim curves. *Default: 0.05*

    :param obj: input surface
    :type obj: abstract.BSplineGeometry, multi.AbstractContainer
    :return: updated surface

def fix_multi_trim_curves(obj, **kwargs):
    """ Fixes direction, connectivity and similar issues of the trim curves.

    This function works for surface trims in curve containers, i.e. trims consisting of multiple curves.

    Keyword Arguments:
        * ``tol``: tolerance value for comparing floats. *Default: 10e-8*
        * ``delta``: evaluation delta of the trim curves. *Default: 0.05*

    :param obj: input surface
    :type obj: abstract.BSplineGeometry, multi.AbstractContainer
    :return: updated surface
    """
    if obj.pdimension != 2:
        raise GeomdlException("Can only work with surfaces")

    # Get keyword arguments
    tol = kwargs.get('tol', 10e-8)
    eval_delta = kwargs.get('delta', 0.05)

    # Loop through the surfaces
    for o in obj:
        # Get the trims
        trims = o.trims

        # Initialize a list for the connected trims
        new_trims = []

        # Traverse through the trims
        for trim in trims:
            trim_size = len(trim)

            # Directly add to the new trims array if the trim is a single curve
            if trim_size == 1:
                new_trims.append(trim)
                continue

            new_trim = []
            for idx in range(0, trim_size):
                # Close the loop
                if idx == trim_size - 1:
                    idx2 = 0
                else:
                    idx2 = idx + 1

                ###
                # Assuming that we have two curves with starting and ending positions defined as P1-P2 and P3-P4,
                # respectively. There are 5 possibilities:
                # 1. P2 = P3 (end of 1st and start of 2nd)
                # 2. P2 = P4 (end of 1st and end of 2nd)
                # 3. P1 = P3 (start of 1st and start of 2nd)
                # 4. P1 = P4 (start of 1st and end of 2nd)
                # 5. the ends of the curves are far away from each other
                ###

                # End of 1st curve vs start of 2nd curve
                if abs(trim[idx].evalpts[-1][0] - trim[idx2].evalpts[0][0]) <= tol and \
                        abs(trim[idx].evalpts[-1][1] - trim[idx2].evalpts[0][1]) <= tol:
                    # They are in the same direction
                    new_trim.append(trim[idx])
                # End of 1st curve vs end of 2nd curve
                elif abs(trim[idx].evalpts[-1][0] - trim[idx2].evalpts[-1][0]) <= tol and \
                        abs(trim[idx].evalpts[-1][1] - trim[idx2].evalpts[-1][1]) <= tol:
                    # Reverse the second curve inplace
                    trim[idx2].reverse()
                    new_trim.append(trim[idx])
                # Start of 1st curve and start of 2nd curve
                elif abs(trim[idx].evalpts[0][0] - trim[idx2].evalpts[0][0]) <= tol and \
                        abs(trim[idx].evalpts[0][1] - trim[idx2].evalpts[0][1]) <= tol:
                    # Reverse the first curve inplace
                    trim[idx].reverse()
                    new_trim.append(trim[idx])
                # Start of 1st curve and end of 2nd curve
                elif abs(trim[idx].evalpts[0][0] - trim[idx2].evalpts[-1][0]) <= tol and \
                        abs(trim[idx].evalpts[0][1] - trim[idx2].evalpts[-1][1]) <= tol:
                    # Reverse both curves inplace
                    trim[idx].reverse()
                    trim[idx2].reverse()
                    new_trim.append(trim[idx])
                # The trim curves are far away from each other
                else:
                    # Find which end is closer to the current trim curve's end point
                    dist1 = linalg.point_distance(trim[idx].evalpts[-1], trim[idx2].evalpts[0])
                    dist2 = linalg.point_distance(trim[idx].evalpts[-1], trim[idx2].evalpts[-1])

                    # Find start and end points of the connector curve
                    start_pt = trim[idx].evalpts[-1]
                    if dist1 < dist2:
                        end_pt = trim[idx2].evalpts[0]
                    else:
                        end_pt = trim[idx2].evalpts[-1]

                    # Generate the connector curve
                    crv = shortcuts.generate_curve()
                    crv.degree = 1
                    crv.ctrlpts = [start_pt, end_pt]
                    crv.knotvector = [0, 0, 1, 1]
                    crv.opt = ['reversed', trim[idx].opt_get('reversed')]

                    # Add trims
                    new_trim.append(trim[idx])
                    new_trim.append(crv)

            # Create a curve container from the new trim list
            cc = shortcuts.generate_container_curve()
            cc.add(new_trim)
            cc.opt = ['reversed', trim.opt_get('reversed')]
            cc.delta = eval_delta

            # Add curve container to the new trims list
            new_trims.append(cc)

        # Update input geometry
        o.trims = new_trims

    return obj