import { Vector } from "./Vector";
/**
 * Check intersection of two bounding boxes.
 * @param bb1 First bounding box
 * @param bb2 Second bounding box
 * @return true if the two bounding boxes intersect each other
 */
export function doBoundsIntersect(bb1, bb2) {
    if (bb1.max.x <= bb2.min.x ||
        bb1.min.x >= bb2.max.x ||
        bb1.max.y <= bb2.min.y ||
        bb1.min.y >= bb2.max.y ||
        bb1.max.z <= bb2.min.z ||
        bb1.min.z >= bb2.max.z) {
        return false;
    }
    return true;
}
/**
 * Check if point is inside a bounding box
 * @param bounds
 * @param point
 * @param deviation positive values extend bounds, negative shrink it
 */
export function isPointInBounds(bounds, point, deviation) {
    if (deviation === void 0) { deviation = 0; }
    if (bounds.max.x + deviation >= point.x &&
        bounds.min.x - deviation <= point.x &&
        bounds.max.y + deviation >= point.y &&
        bounds.min.y - deviation <= point.y &&
        bounds.max.z + deviation >= point.z &&
        bounds.min.z - deviation <= point.z) {
        return true;
    }
    return false;
}
/** check if min and max values are assorted and save it in place */
export function ensureBoundsAreAssorted(bounds) {
    var swap;
    if (bounds.min.x > bounds.max.x) {
        swap = bounds.min.x;
        bounds.min.x = bounds.max.x;
        bounds.max.x = swap;
    }
    if (bounds.min.y > bounds.max.y) {
        swap = bounds.min.y;
        bounds.min.y = bounds.max.y;
        bounds.max.y = swap;
    }
    if (bounds.min.z > bounds.max.z) {
        swap = bounds.min.z;
        bounds.min.z = bounds.max.z;
        bounds.max.z = swap;
    }
    return bounds;
}
/** Convenience function to check if Bounds object is correctly set */
export function areBoundsValid(bounds) {
    var dot = Vector.InnerProduct3(bounds.min, bounds.max);
    return isFinite(dot) && !isNaN(dot);
}
/**
 * Convenience function for creating a Bounds object, cloning the parameters.
 * @param min defaults to  inf / inf / inf
 * @param max defaults to -inf /-inf /-inf
 * */
export function createBounds(min, max) {
    if (min === void 0) { min = Vector.CreateVec3(Infinity, Infinity, Infinity); }
    if (max === void 0) { max = Vector.CreateVec3(-Infinity, -Infinity, -Infinity); }
    var result = {
        min: Vector.CloneVec3(min),
        max: Vector.CloneVec3(max),
    };
    if (areBoundsValid(result)) {
        result = ensureBoundsAreAssorted(result);
    }
    return result;
}
/** Convenience function for cloning a Bounds object */
export function cloneBounds(bounds) {
    return createBounds(bounds.min, bounds.max);
}
/** Function to extend a Bounds object correctly */
export function extendBounds(bounds, point) {
    bounds.min.x = Math.min(bounds.min.x, point.x);
    bounds.min.y = Math.min(bounds.min.y, point.y);
    bounds.min.z = Math.min(bounds.min.z, point.z);
    bounds.max.x = Math.max(bounds.max.x, point.x);
    bounds.max.y = Math.max(bounds.max.y, point.y);
    bounds.max.z = Math.max(bounds.max.z, point.z);
    return bounds;
}
/** Function to extend a Bounds object with another Bounds object, returning new Bounds */
export function mergeBounds(first, second) {
    var merged = cloneBounds(first);
    extendBounds(merged, second.min);
    extendBounds(merged, second.max);
    return merged;
}
/** Convenience function to stringify Bounds */
export function stringifyBounds(bounds, precision) {
    if (precision === void 0) { precision = 3; }
    var result = "{min: {x: " + bounds.min.x.toFixed(precision) + ", y: " + bounds.min.y.toFixed(precision) + ", z: " + bounds.min.z.toFixed(precision) + "}, max: {x: " + bounds.max.x.toFixed(precision) + ", y: " + bounds.max.y.toFixed(precision) + ", z: " + bounds.max.z.toFixed(precision) + "}}";
    return result;
}
/** convenience function to yield the size of Bounds object */
export function getBoundsSize(bounds) {
    var result = Vector.CreateVec3();
    result.x = Math.abs(bounds.max.x - bounds.min.x);
    result.y = Math.abs(bounds.max.y - bounds.min.y);
    result.z = Math.abs(bounds.max.z - bounds.min.z);
    return result;
}
/** convenience function to yield the center of Bounds object */
export function getBoundsCenter(bounds) {
    var result = Vector.ScalarMultiply3(0.5, Vector.Add3(bounds.max, bounds.min));
    return result;
}
/** returns corner points points defined by bounds */
export function getBoundsCorners(bounds) {
    var min = bounds.min;
    var max = bounds.max;
    return [
        Vector.CreateVec3(min.x, min.y, min.z),
        Vector.CreateVec3(min.x, min.y, max.z),
        Vector.CreateVec3(min.x, max.y, min.z),
        Vector.CreateVec3(min.x, max.y, max.z),
        Vector.CreateVec3(max.x, min.y, min.z),
        Vector.CreateVec3(max.x, min.y, max.z),
        Vector.CreateVec3(max.x, max.y, min.z),
        Vector.CreateVec3(max.x, max.y, max.z),
    ];
}
