/** Given the input data will build and return the attributes (vertices and indices for triangles and lines)
 * that is used by WebGl. Using indice, lines and triangles share common vertices to save memory.
 */
export function makeFullMesh(e) {
    const [inputMeshData, inputPropertiesData, isMesh, frame, smoothShading, gridLines,] = e.data;
    function getFloat32ArrayMinMax(data) {
        let max = -99999999;
        let min = 99999999;
        for (let i = 0; i < data.length; i++) {
            max = data[i] > max ? data[i] : max;
            min = data[i] < min ? data[i] : min;
        }
        return [min, max];
    }
    function crossProduct(a, b) {
        const c = [
            a[1] * b[2] - a[2] * b[1],
            a[2] * b[0] - a[0] * b[2],
            a[0] * b[1] - a[1] * b[0],
        ];
        return c;
    }
    function isDefined(x) {
        return typeof x === "number" && !isNaN(x);
    }
    function normalize(a) {
        const L = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
        a[0] /= L;
        a[1] /= L;
        a[2] /= L;
    }
    function calcNormal(w, h, nx, ny, isMesh, smoothShading, meshData, ox, oy, dx, dy) {
        if (!smoothShading) {
            return [1, 1, 1];
        }
        if (!isMesh) {
            return [0, 0, 1];
        }
        const i0 = h * nx + w;
        const i1 = h * nx + (w - 1);
        const i2 = (h + 1) * nx + w;
        const i3 = h * nx + (w + 1);
        const i4 = (h - 1) * nx + w;
        const i0_act = isDefined(meshData[i0]); // eslint-disable-line
        const i1_act = w - 1 >= 0 && isDefined(meshData[i1]); // eslint-disable-line
        const i2_act = h + 1 < ny && isDefined(meshData[i2]); // eslint-disable-line
        const i3_act = w + 1 < nx && isDefined(meshData[i3]); // eslint-disable-line
        const i4_act = h - 1 >= 0 && isDefined(meshData[i4]); // eslint-disable-line
        const noNormal = [0, 0, 0]; // signals a normal could not be calculated.
        if (!i0_act) {
            return noNormal;
        }
        const hh = ny - 1 - h; // Note use hh for h for getting y values.
        const p0 = [ox + w * dx, oy + hh * dy, i0_act ? meshData[i0] : 0]; // eslint-disable-line
        const p1 = [ox + (w - 1) * dx, oy + hh * dy, i1_act ? meshData[i1] : 0]; // eslint-disable-line
        const p2 = [ox + w * dx, oy + (hh + 1) * dy, i2_act ? meshData[i2] : 0]; // eslint-disable-line
        const p3 = [ox + (w + 1) * dx, oy + hh * dy, i3_act ? meshData[i3] : 0]; // eslint-disable-line
        const p4 = [ox + w * dx, oy + (hh - 1) * dy, i4_act ? meshData[i4] : 0]; // eslint-disable-line
        const v1 = [p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]];
        const v2 = [p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2]];
        const v3 = [p3[0] - p0[0], p3[1] - p0[1], p3[2] - p0[2]];
        const v4 = [p4[0] - p0[0], p4[1] - p0[1], p4[2] - p0[2]];
        // Estimating a normal vector at p0:
        // Take cross product of vectors v1, v2,
        // Do this for all 4 quadrants.
        // The resulting normal will be the mean of these four normals.
        //        p2
        //         |
        //   p1 - p0 - p3
        //         |
        //        p4
        const normals = [];
        if (i1_act && i2_act) {
            const normal = crossProduct(v2, v1);
            normals.push(normal);
        }
        if (i2_act && i3_act) {
            const normal = crossProduct(v3, v2);
            normals.push(normal);
        }
        if (i3_act && i4_act) {
            const normal = crossProduct(v4, v3);
            normals.push(normal);
        }
        if (i4_act && i1_act) {
            const normal = crossProduct(v1, v4);
            normals.push(normal);
        }
        if (normals.length === 0) {
            return noNormal;
        }
        const mean = normals[0];
        for (let i = 1; i < normals.length; i++) {
            mean[0] += normals[i][0];
            mean[1] += normals[i][1];
            mean[2] += normals[i][2];
        }
        normalize(mean);
        return mean;
    }
    const meshData = inputMeshData;
    const propertiesData = (inputPropertiesData === null || inputPropertiesData === void 0 ? void 0 : inputPropertiesData.length)
        ? inputPropertiesData
        : meshData;
    // non mesh grids use z = 0 (see below)
    const meshZValueRange = isMesh ? getFloat32ArrayMinMax(meshData) : [0, 0];
    const propertyValueRange = getFloat32ArrayMinMax(propertiesData);
    // Dimensions.
    const ox = frame.origin[0];
    const oy = frame.origin[1];
    const dx = frame.increment[0];
    const dy = frame.increment[1];
    const nx = frame.count[0]; // number of nodes in x direction
    const ny = frame.count[1];
    const propLength = propertiesData.length;
    const isCellCenteredProperties = propLength === (nx - 1) * (ny - 1);
    if (propLength !== (nx - 1) * (ny - 1) && propLength !== nx * ny) {
        console.error("There should be as many property values as nodes (nx*ny) OR as many as cells (nx - 1) * (ny - 1).");
    }
    const nNodes = nx * ny;
    const nCells = (nx - 1) * (ny - 1);
    const nTriangles = nCells * 2;
    const positions = new Float32Array(isCellCenteredProperties ? nCells * 6 * 3 : nNodes * 3);
    const normals = new Float32Array(isCellCenteredProperties || !smoothShading ? 0 : nNodes * 3);
    const triangleIndices = new Uint32Array(nTriangles * 3);
    const vertexProperties = new Float32Array(isCellCenteredProperties ? nCells * 6 : nNodes);
    let nLineIndices = 0;
    if (gridLines) {
        nLineIndices = isCellCenteredProperties
            ? nTriangles * 2 * 2
            : nCells * 4 + (nx - 1) * 2 + (ny - 1) * 2;
    }
    const lineIndices = new Uint32Array(nLineIndices);
    // Note: Assumed layout of the incomming 2D array of data:
    // First coloumn corresponds to lowest x value. Last column highest x value.
    // First row corresponds to max y value. Last row corresponds to lowest y value.
    // This must be taken into account when calculating vertex x,y values and texture coordinates.
    if (!isCellCenteredProperties) {
        // PROPERTIES IS SET INTERPOLATED OVER A CELL.
        // Loop vertices.
        let i = 0;
        for (let h = 0; h < ny; h++) {
            for (let w = 0; w < nx; w++) {
                const i0 = h * nx + w;
                const x0 = ox + w * dx;
                const y0 = oy + (ny - 1 - h) * dy; // See note above.
                const z = isMesh ? meshData[i0] : 0;
                const propertyValue = propertiesData[i0];
                positions[3 * i + 0] = x0;
                positions[3 * i + 1] = y0;
                positions[3 * i + 2] = z;
                if (smoothShading) {
                    const normal = calcNormal(w, h, nx, ny, isMesh, smoothShading, meshData, ox, oy, dx, dy); // eslint-disable-line
                    normals[3 * i + 0] = normal[0];
                    normals[3 * i + 1] = normal[1];
                    normals[3 * i + 2] = normal[2];
                }
                vertexProperties[i] = propertyValue;
                i++;
            }
        }
        // Loop cells.
        i = 0;
        let j = 0;
        for (let h = 0; h < ny - 1; h++) {
            for (let w = 0; w < nx - 1; w++) {
                const i0 = h * nx + w;
                const i1 = h * nx + (w + 1);
                const i2 = (h + 1) * nx + (w + 1);
                const i3 = (h + 1) * nx + w;
                const i0_act = !isMesh ||
                    (isDefined(meshData[i0]) && isDefined(propertiesData[i0])); // eslint-disable-line
                const i1_act = !isMesh ||
                    (isDefined(meshData[i1]) && isDefined(propertiesData[i1])); // eslint-disable-line
                const i2_act = !isMesh ||
                    (isDefined(meshData[i2]) && isDefined(propertiesData[i2])); // eslint-disable-line
                const i3_act = !isMesh ||
                    (isDefined(meshData[i3]) && isDefined(propertiesData[i3])); // eslint-disable-line
                // Triangles.
                if (i1_act && i3_act) {
                    // diagonal i1, i3
                    if (i0_act) {
                        // t1 - i0 provoking index.
                        triangleIndices[i++] = i1;
                        triangleIndices[i++] = i3;
                        triangleIndices[i++] = i0;
                    }
                    if (i2_act) {
                        // t2 - i2 provoking index.
                        triangleIndices[i++] = i1;
                        triangleIndices[i++] = i3;
                        triangleIndices[i++] = i2;
                    }
                }
                else if (i0_act && i2_act) {
                    // diagonal i0, i2
                    if (i1_act) {
                        // t1 - i0 provoking index.
                        triangleIndices[i++] = i1;
                        triangleIndices[i++] = i2;
                        triangleIndices[i++] = i0;
                    }
                    if (i3_act) {
                        // t2 - i2 provoking index.
                        triangleIndices[i++] = i3;
                        triangleIndices[i++] = i0;
                        triangleIndices[i++] = i2;
                    }
                }
                // Lines.
                if (gridLines) {
                    if (i0_act && i1_act) {
                        lineIndices[j++] = i0;
                        lineIndices[j++] = i1;
                    }
                    if (i0_act && i3_act) {
                        lineIndices[j++] = i0;
                        lineIndices[j++] = i3;
                    }
                    if (h == ny - 2 && i2_act && i3_act) {
                        lineIndices[j++] = i3;
                        lineIndices[j++] = i2;
                    }
                    if (w == nx - 2 && i1_act && i2_act) {
                        lineIndices[j++] = i1;
                        lineIndices[j++] = i2;
                    }
                    // diagonal
                    if ((i0_act && !i2_act) || (!i0_act && i2_act)) {
                        lineIndices[j++] = i1;
                        lineIndices[j++] = i3;
                    }
                    // diagonal
                    if ((i3_act && !i1_act) || (!i3_act && i1_act)) {
                        lineIndices[j++] = i0;
                        lineIndices[j++] = i2;
                    }
                }
            }
        }
    }
    else {
        // PROPERTIES IS SET CONSTANT OVER A CELL.
        // Loop cells.
        let i = 0;
        let j = 0;
        let k = 0;
        let l = 0;
        for (let h = 0; h < ny - 1; h++) {
            for (let w = 0; w < nx - 1; w++) {
                const hh = ny - 1 - h; // See note above.
                const i0 = h * nx + w;
                const i1 = h * nx + (w + 1);
                const i2 = (h + 1) * nx + (w + 1);
                const i3 = (h + 1) * nx + w;
                const i0_act = !isMesh || isDefined(meshData[i0]); // eslint-disable-line
                const i1_act = !isMesh || isDefined(meshData[i1]); // eslint-disable-line
                const i2_act = !isMesh || isDefined(meshData[i2]); // eslint-disable-line
                const i3_act = !isMesh || isDefined(meshData[i3]); // eslint-disable-line
                const x0 = ox + w * dx;
                const y0 = oy + hh * dy;
                const z0 = isMesh ? meshData[i0] : 0;
                const x1 = ox + (w + 1) * dx;
                const y1 = oy + hh * dy;
                const z1 = isMesh ? meshData[i1] : 0;
                const x2 = ox + (w + 1) * dx;
                const y2 = oy + (hh - 1) * dy; // Note hh - 1 here.
                const z2 = isMesh ? meshData[i2] : 0;
                const x3 = ox + w * dx;
                const y3 = oy + (hh - 1) * dy; // Note hh - 1 here.
                const z3 = isMesh ? meshData[i3] : 0;
                const propertyIndex = h * (nx - 1) + w; // (nx - 1) -> the width of the property 2D array is one less than for the nodes in this case.
                const propertyValue = propertiesData[propertyIndex];
                if (!isDefined(propertyValue)) {
                    // Inactive cell, dont draw.
                    continue;
                }
                // Triangles.
                if (i1_act && i3_act) {
                    // diagonal i1, i3
                    if (i0_act) {
                        // t1 - i0 provoking index.
                        triangleIndices[i] = i;
                        const L1 = i;
                        i++;
                        positions[j++] = x1;
                        positions[j++] = y1;
                        positions[j++] = z1;
                        triangleIndices[i] = i;
                        const L2 = i;
                        i++;
                        positions[j++] = x3;
                        positions[j++] = y3;
                        positions[j++] = z3;
                        triangleIndices[i] = i;
                        const L3 = i;
                        i++;
                        positions[j++] = x0;
                        positions[j++] = y0;
                        positions[j++] = z0;
                        if (gridLines) {
                            lineIndices[l++] = L3;
                            lineIndices[l++] = L1;
                            lineIndices[l++] = L3;
                            lineIndices[l++] = L2;
                        }
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                    }
                    if (i2_act) {
                        // t2 - i2 provoking index.
                        triangleIndices[i] = i;
                        const L1 = i;
                        i++;
                        positions[j++] = x1;
                        positions[j++] = y1;
                        positions[j++] = z1;
                        triangleIndices[i] = i;
                        const L2 = i;
                        i++;
                        positions[j++] = x3;
                        positions[j++] = y3;
                        positions[j++] = z3;
                        triangleIndices[i] = i;
                        const L3 = i;
                        i++;
                        positions[j++] = x2;
                        positions[j++] = y2;
                        positions[j++] = z2;
                        if (gridLines) {
                            lineIndices[l++] = L1;
                            lineIndices[l++] = L3;
                            lineIndices[l++] = L2;
                            lineIndices[l++] = L3;
                        }
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                    }
                }
                else if (i0_act && i2_act) {
                    // diagonal i0, i2
                    if (i1_act) {
                        //t1 - i0 provoking index.
                        triangleIndices[i] = i;
                        const L1 = i;
                        i++;
                        positions[j++] = x1;
                        positions[j++] = y1;
                        positions[j++] = z1;
                        triangleIndices[i] = i;
                        const L2 = i;
                        i++;
                        positions[j++] = x2;
                        positions[j++] = y2;
                        positions[j++] = z2;
                        triangleIndices[i] = i;
                        const L3 = i;
                        i++;
                        positions[j++] = x0;
                        positions[j++] = y0;
                        positions[j++] = z0;
                        if (gridLines) {
                            lineIndices[l++] = L1;
                            lineIndices[l++] = L3;
                            lineIndices[l++] = L1;
                            lineIndices[l++] = L2;
                        }
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                    }
                    if (i3_act) {
                        // t2 - i2 provoking index.
                        triangleIndices[i] = i;
                        const L1 = i;
                        i++;
                        positions[j++] = x3;
                        positions[j++] = y3;
                        positions[j++] = z3;
                        triangleIndices[i] = i;
                        const L2 = i;
                        i++;
                        positions[j++] = x0;
                        positions[j++] = y0;
                        positions[j++] = z0;
                        triangleIndices[i] = i;
                        const L3 = i;
                        i++;
                        positions[j++] = x2;
                        positions[j++] = y2;
                        positions[j++] = z2;
                        if (gridLines) {
                            lineIndices[l++] = L1;
                            lineIndices[l++] = L2;
                            lineIndices[l++] = L1;
                            lineIndices[l++] = L3;
                        }
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                        vertexProperties[k++] = propertyValue;
                    }
                }
            }
        }
    }
    const webworkerReturnData = [
        positions,
        normals,
        triangleIndices,
        vertexProperties,
        lineIndices,
        meshZValueRange,
        propertyValueRange,
    ];
    return webworkerReturnData;
}
//# sourceMappingURL=webworker.js.map