export class AbstractShape3D {
    /**
     * Signed distance to boundary of the shape from the given point
     * @param {number[]} point
     * @returns {number}
     */
    signed_distance_at_point(point) {
        throw new Error('Not Implemented');
    }

    /**
     * Samples both distances as well as the gradient
     * @param {number[]} result resulting gradient is written here
     * @param {number[]} point sampling point
     * @returns {number}
     */
    signed_distance_gradient_at_point(result, point) {
        throw new Error('Not Implemented');
    }

    /**
     *
     * @param {number[]} result where the resulting point is stored
     * @param {number[]} reference reference point from which to go
     * @returns {void}
     */
    nearest_point_on_surface(result, reference) {
        throw new Error('Not Implemented');
    }

    /**
     *
     * @param {number[]} result
     * @param {number} result_offset
     * @param {function} random
     * @returns {void}
     */
    sample_random_point_in_volume(result, result_offset, random) {
        throw new Error('Not Implemented');
    }

    /**
     * Whether or not given point is inside the shape
     * @param {number[]} point
     * @returns {boolean}
     */
    contains_point(point) {
        throw new Error('Not Implemented');
    }

    /**
     * Total volume of the shape
     * @returns {number}
     */
    get volume() {
        throw new Error('Not Implemented');
    }

    /**
     * @returns {number}
     */
    get surface_area() {
        throw new Error('Not Implemented');
    }

    /**
     *
     * @param {number[]|ArrayLike<number>|Float32Array|Float64Array} result format: x0,y0,z0,x1,y1,z1
     * @returns {void}
     */
    compute_bounding_box(result) {
        throw new Error('Not Implemented');
    }

    /**
     * Support function, given a direction vector, return point on the shape that's furthest in that direction
     * Assumes direction is a unit vector
     * @param {number[]|Float32Array|Float64Array} result
     * @param {number} result_offset
     * @param {number} direction_x
     * @param {number} direction_y
     * @param {number} direction_z
     * @returns {void}
     */
    support(result, result_offset, direction_x, direction_y, direction_z) {
        throw new Error("Not Implemented");
    }

    /**
     * @template {AbstractShape3D} T
     * @param {T} other
     * @returns {boolean}
     */
    equals(other) {
        return this.constructor === other.constructor;
    }

    /**
     *
     * @returns {number}
     */
    hash() {
        return 0;
    }
}

/**
 * Whether this shape is convex.
 *
 * Convex shapes can be fed directly into GJK/EPA via their {@link support}
 * function — the Minkowski difference of two convex sets is itself convex,
 * which is the precondition GJK relies on. Non-convex shapes (heightmaps,
 * arbitrary meshes, unions of convex shapes) violate that precondition: the
 * support operator is still definable as `argmax (p · d)`, but feeding it to
 * GJK will produce false negatives where the algorithm walks into a
 * concavity and reports "no overlap" between intersecting bodies.
 *
 * The narrowphase reads this flag to gate Minkowski-based pair dispatch.
 * When `false`, a dedicated path is required (grid traversal for heightmaps,
 * per-triangle GJK for meshes, per-child decomposition for unions).
 *
 * Default is `true` — convex is the common case across primitives. Each
 * non-convex subclass overrides this on its own prototype.
 *
 * @readonly
 * @type {boolean}
 */
AbstractShape3D.prototype.is_convex = true;
