GetAreas = function(index,x,y,varargin) {
    //GETAREAS - compute areas or volumes of elements
    //
    //   compute areas of triangular elements or volumes 
    //   of pentahedrons
    //
    //   Usage:
    //      areas  =GetAreas(index,x,y);
    //      volumes=GetAreas(index,x,y,z);
    //
    //   Examples:
    //      areas  =GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
    //      volumes=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y,md.z);

    //get number of elements and number of nodes
    function zeros(...args) {
        var array = [];
        for (var i = 0; i < args[0]; ++i) {
            array.push(args.length == 1 ? 0 : zeros(args.slice(1)));
        }
        return array;
    }
    nels=index.length;
    nods=x.length;
    if (arguments.length===4)
        z=varargin[0];

    //some checks
    if (arguments.length!==3 && arguments.length!==4) {
        //help GetAreas
        console.error('GetAreas error message: bad usage')
    }
    if ((y.length!==nods) || (arguments.length===4 && z.length!==nods)) {
        console.error('GetAreas error message: x,y and z do not have the same length')
    }
    if (Math.max.apply(null, index)>nods) {
        console.error(['GetAreas error message: index should not have values above ' + nods.toString() ]);
    }
    if ((arguments.length===3 && index[0].length!==3)) {
        console.error('GetAreas error message: index should have 3 columns for 2d meshes.')
    }
    if ((arguments.length===4 && index[0].length!==6)) {
        console.error('GetAreas error message: index should have 6 columns for 3d meshes.')
    }

    //initialization
    areas=zeros(nels,1);

    var getColumnArray = function(arr, col) {
       return arr.map(function(value,index) { return value[col]; }); 
    };

    x1=getColumnArray(index, 0).map(function(value) { return x[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
    x2=getColumnArray(index, 1).map(function(value) { return x[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
    x3=getColumnArray(index, 2).map(function(value) { return x[value]; }).map(function(v) { return v === undefined ? 0 : v; });
    y1=getColumnArray(index, 0).map(function(value) { return y[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
    y2=getColumnArray(index, 1).map(function(value) { return y[value]; }).map(function(v) { return v === undefined ? 0 : v; }); 
    y3=getColumnArray(index, 2).map(function(value) { return y[value]; }).map(function(v) { return v === undefined ? 0 : v; });

    //compute the volume of each element
    if (arguments.length===3) {
        //compute the surface of the triangle
        areas=math.multiply(0.5, math.subtract(math.multiply(math.subtract(x2,x1), math.subtract(y3,y1)), math.multiply(math.subtract(y2,y1), math.subtract(x3,x1))));
    } else {
        //V=area(triangle)*1/3(z1+z2+z3)

        var tempind1 = [];
        index.forEach(function(value, idx) {
            tempind1.push(value[3]);
            tempind1.push(value[4]);
            tempind1.push(value[5]);
        });

        var tempind2 = [];
        index.forEach(function(value, idx) {
            tempind2.push(value[0]);
            tempind2.push(value[1]);
            tempind2.push(value[2]);
        });
        
        var tempz1 = tempind1.map(function(value, idx) {
            return z[value][2];
        });

        var tempz2 = tempind2.map(function(value, idx) {
            return z[value][2];
        })

        thickness = math.subtract(math.mean(tempz1), math.mean(tempz2));

        areas=math.multiply(math.multiply(0.5, math.subtract(math.multiply(math.subtract(x2,x1), math.subtract(y3,y1)), math.multiply(math.subtract(y2,y1), math.subtract(x3,x1)))), thickness);
    }

    return areas;
};
