import numpy as np

def compute_faces_area(V, F):
    """
    Computes the area of the faces of a given triangle mesh (V, F).

    Input:
    - V : np.array (|V|, 3)
        The array of vertices positions.
        Contains the coordinates of the i-th vertex in i-th row
    - F : np.array (|F|, 3)
        The array of triangle faces.
    Output:
    - area : np.array (|F|,)
        The area of the faces. The i-th position contains the area of the i-th
        face.
    """
    
    # HW.1.3.3
    return np.linalg.norm(np.cross(V[F[:,1]] - V[F[:,0]],V[F[:,2]] - V[F[:,0]], axis=1), axis=1)/2.0


def compute_mesh_area(V, F):
    """
    Computes the area of a given triangle mesh (V, F).

    Input:
    - V : np.array (|V|, 3)
        The array of vertices positions.
        Contains the coordinates of the i-th vertex in i-th row
    - F : np.array (|F|, 3)
        The array of triangle faces.
    Output:
    - area : float
        The area of the mesh.
    """

    # HW.1.3.3
    return np.sum(compute_faces_area(V,F))


def compute_faces_centroid(V, F):
    """
    Computes the area centroid of each face of a given triangle mesh (V, F).

    Input:
    - V : np.array (|V|, 3)
        The array of vertices positions.
        Contains the coordinates of the i-th vertex in i-th row
    - F : np.array (|F|, 3)
        The array of triangle faces.
    Output:
    - cf : np.array (|F|, 3)
        The area centroid of the faces.
    """

    # HW.1.3.4
    return  (V[F[:,0]]+ V[F[:,1]] + V[F[:,2]])/3.0


def compute_mesh_centroid(V, F):
    """
    Computes the area centroid of a given triangle mesh (V, F).

    Input:
    - V : np.array (|V|, 3)
        The array of vertices positions.
        Contains the coordinates of the i-th vertex in i-th row
    - F : np.array (|F|, 3)
        The array of triangle faces.
    Output:
    - centroid : np.array (3,)
        The area centroid of the mesh.
    """

    # HW.1.3.4
    face_centroid = compute_faces_centroid(V,F)
    face_area = compute_faces_area(V,F)
    return 1.0/np.sum(face_area) * np.sum(np.einsum('i,ij->ij', face_area, face_centroid), axis=0)


def compute_center_support_line(V):
    """
    Computes the x coordinate of the center of the support line

    Input:
    - V : np.array (|V|, 3)
        The array of vertices positions.
        Contains the coordinates of the i-th vertex in i-th row

    Output:
    - x_csl : float
        the x coordinate of the center of the support line
    """

    # HW.1.3.5
    support_v = np.fromiter((v[0] for v in V if v[1]<10**-5), dtype=V.dtype)
    x_csl = np.amin(support_v)+(np.amax(support_v)-np.amin(support_v))/2

    return x_csl
