def METHOD_NAME(pointclouds, planes, plot_path=None):
    """Plots list of pointclouds and planes with plotly
    Parameters
    ----------
    pointclouds : list of ndarray
        List of (n x 3) ndarrays with coordintes of points to be plotted
    planes : list of ndarray
        List of ndarrays (vectors of length 4) containing plane parameters
    plot_path: String or None, optional
        Filename for storing plot as html. If None, plot is displayed but not
        saved. Default: None.
    Returns
    -------
        None
    """
    fig = go.Figure()
    for i, pc in enumerate(pointclouds):
        sample_size = min(10000, pc.shape[0])
        indices = np.random.choice(pc.shape[0], sample_size, replace=False)
        pc_rs = pc[indices]
        marker_size = 1
        if pc_rs.shape[0] < 10:
            marker_size = 5
        fig.add_trace(
            go.Scatter3d(
                x=pc_rs.T[0],
                y=pc_rs.T[1],
                z=pc_rs.T[2],
                mode="markers",
                marker=dict(size=marker_size),
                showlegend=True,
                name="pointcloud" + str(i),
            )
        )
    cmin = 0
    cmax = len(planes) - 1
    colorscale = "rainbow"
    for i, plane in enumerate(planes):
        # x, y, z = plane_to_rectuangular_grid(plane, -6, 6, 4, 14)
        x, y, z = plane_to_isosceles_trapezoid_grid(plane, 2, 8, 4, 14)
        surfacecolor = i * np.ones(shape=z.shape)
        fig.add_trace(
            go.Surface(
                x=x,
                y=y,
                z=z,
                name="plane" + str(i),
                surfacecolor=surfacecolor,
                cmin=cmin,
                cmax=cmax,
                colorscale=colorscale,
                showscale=False,
                showlegend=True,
            )
        )
    now = datetime.now()
    fig.update_layout(title="Pointcloud and plane(s) generated on " + str(now))
    if plot_path is None:
        fig.show()
    else:
        fig.write_html(plot_path, auto_open=True)