def find_best_angle_ratio(
    polygon1: List[List[int]],
    polygon2: List[List[int]],
    initial_parameters: Tuple[float, float],
    x: float,
    y: float,
    angle_target: float,
    max_iters: int = 100,
    iou_threshold: float = 0.7,
) -> Tuple[float, float]:
    """
    Find the best angle and scaling ratio to maximize IoU (Intersection over Union) while satisfying a constraint.

    Args:
        polygon1 (List[List[int]]): List of vertices of the first polygon.
        polygon2 (List[List[int]]): List of vertices of the second polygon.
        initial_parameters (Tuple[float, float]): Initial parameters for optimization (angle, ratio).
        x (float): X-coordinate of the center point for transformation.
        y (float): Y-coordinate of the center point for transformation.
        angle_target (float): Target angle for optimization.
        max_iters (int, optional): Maximum number of iterations for optimization (default is 100).
        iou_threshold (float, optional): IoU threshold for the constraint (default is 0.7).

    Returns:
        Tuple[float, float]: The optimal angle and scaling ratio.
    """

    # Define the optimization target function
    def target_function(parameters: Tuple[float, float]) -> float:
        iou, in_iou = align_and_compute_iou(polygon1, polygon2, x, y, parameters)
        return -iou - 0.1 * in_iou + 0.1 * angle_loss(angle_target, parameters)

    # Define the constraint function
    def constraint_function(parameters: Tuple[float, float]) -> float:
        iou, _ = align_and_compute_iou(polygon1, polygon2, x, y, parameters)
        return iou - iou_threshold

    # Define the angle loss function
    def angle_loss(angle_target: float, parameters: Tuple[float, float]) -> float:
        loss = (angle_target - parameters[0]) ** 2
        return loss

    # Define the transformation and IoU calculation function
    def align_and_compute_iou(
        polygon1: List[List[int]],
        polygon2: List[List[int]],
        x: float,
        y: float,
        parameters: Tuple[float, float],
    ) -> float:
        angle, ratio = parameters

        # Create a rotation matrix
        rotation_matrix = np.array(
            [
                [np.cos(np.radians(angle)), -np.sin(np.radians(angle))],
                [np.sin(np.radians(angle)), np.cos(np.radians(angle))],
            ]
        )

        # Translate the polygon to the origin
        translated_polygon = polygon1 - [x, y]

        # Rotate the translated polygon
        rotated_polygon = np.dot(translated_polygon, rotation_matrix.T)

        # Scale the rotated polygon
        scaled_polygon = rotated_polygon * ratio

        # Translate the scaled polygon back to its original position
        polygon1_transformed = scaled_polygon + [x, y]

        # Create Shapely polygon objects
        poly1 = Polygon(polygon1_transformed)
        poly2 = Polygon(polygon2)

        # Calculate IoU
        try:
            iou = poly1.intersection(poly2).area / poly1.union(poly2).area
            in_iou = poly1.intersection(poly2).area / poly2.area
        except Exception as e:
            print(f"Warning: Optimize polygon but have error of {e}. Fix it automatically")
            if not poly1.is_valid:
                poly1 = poly1.buffer(0)
            if not poly2.is_valid:
                poly2 = poly2.buffer(0)

            iou = poly1.intersection(poly2).area / poly1.union(poly2).area
            in_iou = poly1.intersection(poly2).area / poly2.area

        return iou, in_iou

    # Define the constraint
    constraint = {"type": "ineq", "fun": constraint_function}

    # Define optimization options, including learning rate
    options = {"disp": True, "maxiter": max_iters, "ftol": 1e-6, "eps": 1e-5}

    # Define parameter bounds
    bounds = [(angle_target - 10, angle_target + 10), (0.1, 3.0)]

    # Perform the optimization to maximize IoU while satisfying the constraint
    result = minimize(
        target_function,
        initial_parameters,
        method="SLSQP",
        constraints=constraint,
        options=options,
        bounds=bounds,
    )

    # Get the optimal parameters and maximum IoU value
    optimal_parameters = result.x
    -result.fun

    return optimal_parameters[0], optimal_parameters[1]

    Find the best angle and scaling ratio to maximize IoU (Intersection over Union) while satisfying a constraint.

    Args:
        polygon1 (List[List[int]]): List of vertices of the first polygon.
        polygon2 (List[List[int]]): List of vertices of the second polygon.
        initial_parameters (Tuple[float, float]): Initial parameters for optimization (angle, ratio).
        x (float): X-coordinate of the center point for transformation.
        y (float): Y-coordinate of the center point for transformation.
        angle_target (float): Target angle for optimization.
        max_iters (int, optional): Maximum number of iterations for optimization (default is 100).
        iou_threshold (float, optional): IoU threshold for the constraint (default is 0.7).

    Returns:
        Tuple[float, float]: The optimal angle and scaling ratio.
    
scripts/easyphoto_utils/tryon_utils.py