import numpy as np
# -----------------------------------------------------------------------------
#                               Mesh geometry
# -----------------------------------------------------------------------------

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.
    """

    # HW1 1.3.3
    trig_area = lambda fi:  ((V[fi[0]][1] - V[fi[1]][1]) * V[fi[2]][0]+ (V[fi[2]][1] - V[fi[0]][1]) * V[fi[1]][0] + (V[fi[1]][1] - V[fi[2]][1]) * V[fi[0]][0])/2.0
    area = np.array([trig_area(fi) for fi in F])
    return area


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.
    """

    # HW1 1.3.3 
    area = np.sum(compute_faces_area(V,F))

    return area


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.
    """
    
    # HW1 1.3.4
    cent_x = lambda fi:  (V[fi[0]][0] + V[fi[1]][0] + V[fi[2]][0])/3.0
    cent_y = lambda fi:  (V[fi[0]][1] + V[fi[1]][1] + V[fi[2]][1])/3.0
    cent_idx = lambda fi: [cent_x(fi), cent_y(fi), 0]
        
    cf = np.array([cent_idx(fi) for fi in F])

    return cf


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.
    """

    # HW1 1.3.4
    face_centroid = compute_faces_centroid(V,F)
    mesh_area= compute_mesh_area(V,F)
    face_area = compute_faces_area(V,F)
    
    face_centroid_x = face_centroid[:,0]
    face_centroid_y = face_centroid[:,1]
    face_centroid_z = face_centroid[:,2]
    
    mc = np.array([np.sum(np.dot(face_centroid_x,face_area))/mesh_area,         np.sum(np.dot(face_centroid_y,face_area))/mesh_area, 0])
    
    return mc

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
    """
    
    # HW1 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
