int NgonGridDataDecomposer::isFacetValid(double* z, double* values, int perNodeValues, int numX, int numY, int i, int j, int logUsed, int currentEdgeValid, int* nextEdgeValid)
{
    *nextEdgeValid = isFacetEdgeValid(z, values, perNodeValues, numX, numY, i+1, j, logUsed);

    if (currentEdgeValid && *nextEdgeValid)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int NgonGridGrayplotDataDecomposer::isFacetValid(double* z, double* values, int perNodeValues, int numX, int numY, int i, int j, int logUsed, int currentEdgeValid, int* nextEdgeValid)
{
    *nextEdgeValid = isFacetEdgeValid(z, values, perNodeValues, numX, numY, i + 1, j, logUsed);

    if (!perNodeValues)
    {
        /*
         * Grid values are defined per facet.
         * In addition to edge validity, which in this case is determined only by z coordinates, the
         * facet's (i,j) value must also be read in order to determine its overall validity.
         */
        double zij = getValue(values, numX, numY, i, j);

        if (DecompositionUtils::isValid(zij) && currentEdgeValid && *nextEdgeValid)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        /*
         * Grid values are defined per node, and have therefore been already used
         * to determine edge validity
         */
        if (currentEdgeValid && *nextEdgeValid)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}
/*
 * To do: merge with Plot3DDecomposer::fillWireIndices, as these functions perform a lot of redundant work.
 */
int NgonGridDataDecomposer::fillTriangleIndices(int* buffer, int bufferLength, int logMask, double* x, double* y, double* z, double* values, int perNodeValues, int numX, int numY)
{
    int bufferOffset = 0;

    int currentRowValid = 0;
    int nextRowValid = 0;

    int currentColumnValid = 0;
    int nextColumnValid = 0;

    int currentEdgeValid = 0;
    int nextEdgeValid = 0;

    int currentFacetValid = 0;

    int ij = 0;
    int ip1j = 0;
    int ip1jp1 = 0;
    int ijp1 = 0;

    /* 0 indices if less than 2 points along either dimension */
    if (numX < 2 || numY < 2)
    {
        return 0;
    }

    /* First row */
    currentRowValid = DecompositionUtils::isValid(y[0]);

    if (logMask & 0x2)
    {
        currentRowValid &= DecompositionUtils::isLogValid(y[0]);
    }

    /* To do: optimize */
    for (int j = 0; j < numY-1; j++)
    {
        nextRowValid = DecompositionUtils::isValid(y[j+1]);

        if (logMask & 0x2)
        {
            nextRowValid &= DecompositionUtils::isLogValid(y[j+1]);
        }

        if (!currentRowValid || !nextRowValid)
        {
            currentRowValid = nextRowValid;
            continue;
        }
        else
        {
            currentRowValid = nextRowValid;
        }

        currentColumnValid = DecompositionUtils::isValid(x[0]);

        if (logMask & 0x1)
        {
            currentColumnValid &= DecompositionUtils::isLogValid(x[0]);
        }

        ij = getPointIndex(numX, numY, 0, j);
        ijp1 = getPointIndex(numX, numY, 0, j+1);

        currentEdgeValid = isFacetEdgeValid(z, values, perNodeValues, numX, numY, 0, j, logMask & 0x4);

        for (int i = 0; i < numX-1; i++)
        {
            nextColumnValid = DecompositionUtils::isValid(x[i+1]);

            if (logMask & 0x1)
            {
                nextColumnValid &= DecompositionUtils::isLogValid(x[i+1]);
            }

            ip1j = getPointIndex(numX, numY, i+1, j);
            ip1jp1 = getPointIndex(numX, numY, i+1, j+1);

            currentFacetValid = isFacetValid(z, values, perNodeValues, numX, numY, i, j, logMask & 0x4, currentEdgeValid, &nextEdgeValid);

            if (currentColumnValid && nextColumnValid && (currentFacetValid))
            {
                int facetVertexIndices[4];
                int triangleVertexIndices[6];
                int firstVertexIndex;

#if PER_VERTEX_VALUES
                facetVertexIndices[0] = ij;
                facetVertexIndices[1] = ip1j;
                facetVertexIndices[2] = ip1jp1;
                facetVertexIndices[3] = ijp1;
#else
                firstVertexIndex = getFirstVertexIndex(numX, numY, i, j);

                facetVertexIndices[0] = firstVertexIndex;
                facetVertexIndices[1] = firstVertexIndex+1;
                facetVertexIndices[2] = firstVertexIndex+3;
                facetVertexIndices[3] = firstVertexIndex+2;
#endif

                getFacetTriangles(x, y, z, numX, numY, i, j, facetVertexIndices, triangleVertexIndices);

                buffer[bufferOffset] = triangleVertexIndices[0];
                buffer[bufferOffset+1] = triangleVertexIndices[1];
                buffer[bufferOffset+2] = triangleVertexIndices[2];
                buffer[bufferOffset+3] = triangleVertexIndices[3];
                buffer[bufferOffset+4] = triangleVertexIndices[4];
                buffer[bufferOffset+5] = triangleVertexIndices[5];

                bufferOffset += 6;
            }

            currentColumnValid = nextColumnValid;

            currentEdgeValid = nextEdgeValid;

            ij = ip1j;
            ijp1 = ip1jp1;
        }
    }

    return bufferOffset;
}