def METHOD_NAME(self, max_power, pre_scale=1, post_scale=1):
    """ Return a new instance with clamped power.
    :param max_power: power
    :type max_power: numeric
    :param pre_scale: scaling factor applied to all points before clamping
    :type pre_scale: numeric
    :param post_scale: scaling factor applied to all points after clamping
    :type post_scale: numeric
    :return: loating curve
    :rtype: object
    """
    pre_scaled_points = [(p[0], pre_scale*p[1]) for p in self.points]
    new_points = []
    for i, p in enumerate(pre_scaled_points):
        if i + 1 >= len(pre_scaled_points):
            new_points.append((p[0], min(max_power, p[1])))
            break
        next_point = self.points[i + 1]
        soc_a = p[0]
        soc_b = next_point[0]
        pow_a = p[1]
        pow_b = next_point[1]
        if pow_a <= max_power and pow_b <= max_power:
            new_points.append((p[0], p[1]))
        elif pow_a >= max_power and pow_b >= max_power:
            new_points.append((p[0], max_power))
        elif pow_a <= max_power and pow_b >= max_power:
            new_points.append((p[0], p[1]))
            # intersect lines
            t = (max_power - pow_a) / (pow_b - pow_a)
            soc = soc_a + (soc_b - soc_a) * t
            new_points.append((soc, max_power))
        elif pow_a >= max_power and pow_b <= max_power:
            new_points.append((p[0], max_power))
            # intersect lines
            t = (max_power - pow_a) / (pow_b - pow_a)
            soc = soc_a + (soc_b - soc_a) * t
            new_points.append((soc, max_power))
    post_scaled = [(p[0], post_scale*p[1]) for p in new_points]
    return LoadingCurve(post_scaled)