def accessibility_cost(scene, a, b, normal, visualize=False, fast=True):
    """
    Computes how much objs b block front access to a. b obj blockages are not summed.
    the closest b obj to a is taken as the representative blockage
    """

    if isinstance(a, str):
        a = [a]
    if isinstance(b, str):
        b = [b]

    b = [b_name for b_name in b if b_name not in a]
    if len(b) == 0:
        return 0

    if visualize:
        fig, ax = plt.subplots()
    a_trimeshes = iu.meshes_from_names(scene, a)
    b_trimeshes = iu.meshes_from_names(scene, b)

    a_objs = iu.blender_objs_from_names(a)
    iu.blender_objs_from_names(b)

    score = 0
    for a_name, a_obj, a_trimesh in zip(a, a_objs, a_trimeshes):
        a_centroid = a_trimesh.centroid

        front_plane_pt = a_centroid
        front_plane_normal = np.array(a_obj.matrix_world.to_3x3() @ Vector(normal))

        a_centroid_proj = (
            a_centroid
            - np.dot(a_centroid - front_plane_pt, front_plane_normal)
            * front_plane_normal
        )

        if fast:
            # get the closest centroid in b and the mesh that it belongs to
            b_centroids = [b_trimesh.centroid for b_trimesh in b_trimeshes]
            distances = [np.linalg.norm(pt - a_centroid_proj) for pt in b_centroids]
            min_index = np.argmin(distances)
            b_closest_pt = b_centroids[min_index]
            b_chosen = b[min_index]
        else:
            # might need to change this to closest pt on the frontal plane
            res = min_dist(scene, a_name, b)
            b_chosen = res.names[1] if res.names[0] == a_name else res.names[0]
            b_closest_pt = res.data.point(b_chosen)

        centroid_to_b = b_closest_pt - a_centroid_proj

        dist = np.linalg.norm(centroid_to_b)
        bounds = iu.meshes_from_names(scene, b_chosen)[0].bounds
        diag_length = np.linalg.norm(bounds[1] - bounds[0])
        if np.dot(centroid_to_b, front_plane_normal) < 0:
            continue
        # cos theta/dist
        score += (np.dot(centroid_to_b, front_plane_normal) / dist**2) * diag_length
        if visualize:
            ax.plot(
                [a_centroid_proj[0], b_closest_pt[0]],
                [a_centroid_proj[1], b_closest_pt[1]],
                color="red",
            )
            # plot source and target geoms
            iu.plot_geometry(ax, a_trimesh, "blue")
            iu.plot_geometry(ax, iu.meshes_from_names(scene, b_chosen)[0], "green")
            # plot front plane
            # plot_geometry(ax, planes.extract_tagged_plane(a_obj, a_tag, a_front_plane), 'black')
            # plot centroid
            ax.plot(
                a_centroid_proj[0],
                a_centroid_proj[1],
                "o",
                color="black",
                label="Centroid of a",
            )

    if visualize:
        plt.show()
    return score

    Computes how much objs b block front access to a. b obj blockages are not summed.
    the closest b obj to a is taken as the representative blockage
    
infinigen/core/constraints/evaluator/node_impl/trimesh_geometry.py