declare module 'd3-quadtree' {
  export interface Quadtree<T> {
    data(): T[]
    search?(x: number, y: number, radius?: number): T | undefined
  }

  export function quadtree<T>(data?: T[]): Quadtree<T>
}

declare module 'd3-delaunay' {
  export class Delaunay {
    constructor(points: Float64Array | ArrayLike<number>)

    static from(
      points: ArrayLike<[number, number]> | ArrayLike<ArrayLike<number>>,
    ): Delaunay

    halfedges: Int32Array
    hull: Int32Array
    inedges: Int32Array
    points: Float64Array
    triangles: Int32Array

    find(x: number, y: number, startingIndex?: number): number
    update(): void
    voronoi(bounds: [number, number, number, number]): Voronoi
  }

  export interface Voronoi {
    circumcenters: Float64Array
    vectors: Float64Array
    delaunay: Delaunay
    cellPolygons(): [number, number][][]
    cellPolygon(i: number): [number, number][] | null
  }
}

import { CV } from '@techstark/opencv-js';
import { default as default_2 } from 'kdbush';
import { Delaunay } from 'd3-delaunay';
import { MeydaAudioFeature } from 'meyda';
import { MeydaFeaturesObject } from 'meyda';
import { Quadtree } from 'd3-quadtree';
import { Voronoi } from 'd3-delaunay';

/**
 * Returns the absolute value of a number (the value without regard to whether it is positive or negative).
 * For example, the absolute value of -5 is the same as the absolute value of 5.
 * @param x A numeric expression for which the absolute value is needed.
 */
declare function abs(x: number): number;

/**
 * Returns the arc cosine (or inverse cosine) of a number.
 * @param x A numeric expression.
 */
declare function acos(x: number): number;

/**
 * Returns the inverse hyperbolic cosine of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function acosh(x: number): number;

/** Array of all direction vectors both `DIRECTIONS` and `DIAGONALS` starting with East going clockwise */
export declare const ALL_DIRECTIONS: Vector<2>[];

export declare type AnyVector<N extends number = number> = Vector<N> | Float32Vector<N> | Float64Vector<N> | Int8Vector<N> | Int16Vector<N> | Int32Vector<N> | Uint8Vector<N> | Uint8ClampedVector<N> | Uint16Vector<N> | Uint32Vector<N>;

declare class Arc extends Geometry {
    x: number;
    y: number;
    radius: number;
    startAngle: number;
    endAngle: number;
    counterclockwise?: boolean | undefined;
    constructor(options: GeometricOptions, x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean | undefined);
    _svg(): SVGCircleElement;
    _canvas(ctx: CanvasRenderingContext2D): void;
}

export declare type ArcOptions = GeometricOptions;

declare const ArrayVectorBase: VectorBaseConstructor;

/**
 * Returns the arcsine of a number.
 * @param x A numeric expression.
 */
declare function asin(x: number): number;

/**
 * Returns the inverse hyperbolic sine of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function asinh(x: number): number;

/**
 * Returns the arctangent of a number.
 * @param x A numeric expression for which the arctangent is needed.
 */
declare function atan(x: number): number;

/**
 * Returns the angle (in radians) from the X axis to a point.
 * @param y A numeric expression representing the cartesian y-coordinate.
 * @param x A numeric expression representing the cartesian x-coordinate.
 */
declare function atan2(y: number, x: number): number;

/**
 * Returns the inverse hyperbolic tangent of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function atanh(x: number): number;

/**
 * Audio class for analyzing audio from web browser
 * Provides real-time access to FFT data, amplitude, and advanced audio features via Meyda
 */
declare class Audio_2 {
    private audioContext;
    private analyser;
    private lastBeatTime;
    private beatIntervals;
    private energyHistory;
    private readonly maxBeatIntervals;
    private readonly historySize;
    /**
     * Create and initialize an Audio instance
     * @param fftSize Size of FFT analysis (default: 2048)
     * @returns Promise that resolves with initialized Audio instance
     */
    static create(fftSize?: number): Promise<Audio_2>;
    private constructor();
    /**
     * Extract audio features using Meyda
     * @param features Array of feature names to extract, or 'all' for all available features
     * @returns Object containing the requested audio features
     */
    getFeatures(features?: Feature[] | Feature | 'all'): FeatureResult;
    /**
     * Calculate BPM using energy-based beat detection
     * @param energy Current energy value from Meyda
     * @returns Current BPM estimate, or undefined if not enough data
     */
    private calculateBPM;
    /**
     * Start a feature extraction stream with callback
     * @param callback Function called with extracted features at each interval
     * @param features Features to extract ('all' or array of feature names)
     * @param fps Frames per second for feature extraction (default: 30)
     * @returns Function to call to stop the stream
     */
    startStream(callback: (features: Partial<MeydaFeaturesObject>) => void, features?: Feature[] | 'all', fps?: number): () => void;
}
export { Audio_2 as Audio }

export declare class Bitmap {
    readonly width: number;
    readonly height: number;
    private readonly data;
    static create(width: number, height: number): Bitmap;
    static fromBooleanMatrix(matrix: boolean[][]): Bitmap;
    static fromUnit8array(width: number, height: number, data: Uint8Array): Bitmap;
    constructor(width: number, height: number, data: Uint8Array);
    coordsToIndex(x: number, y: number): number;
    /** return if coordinates are within bounds */
    bounds(x: number, y: number): boolean;
    /** Convert an index to the x,y value of that index top left corner being [0,0]  */
    indexToCoords(i: number): [number, number];
    clone(): Bitmap;
    /** The amount of bits in this map */
    size(): number;
    get(x: number, y: number): boolean;
    /** Get a bit by index, generally faster than setting with (x,y) coordinates */
    getByIndex(i: number): boolean;
    set(x: number, y: number, value: boolean): void;
    /** Set a bit by index, generally faster than setting with (x,y) coordinates */
    setByIndex(i: number, value: boolean): void;
    toggle(x: number, y: number): void;
    toPrettyString(): string;
    /**
     * Use [Zhang-Suen thinning algorithm](https://rosettacode.org/wiki/Zhang-Suen_thinning_algorithm)
     * to thin the shapes made by each set of 1 bits */
    thin(): Bitmap;
    /** Get all points that have a false neighbor using 4 connectivity (left, top, right, down) */
    boundaryPoints(): Vector<2>[];
    /** Go over each bit value */
    forEach(cb: (value: boolean, index: number) => void): void;
    /**
     * Voronoi-based skeletonization
     * Creates a skeleton by finding the [medial axis](https://en.wikipedia.org/wiki/Medial_axis) using Voronoi diagram of boundary points
     *
     * returns a list of floating point numbers that are approximately inside of the bitmap
     */
    toSkeleton(): [number, number][];
    contours(opts?: ContourExtractorOpts): Tree<Contour>;
}

export declare class Canvas<R extends RenderMode> {
    readonly width: number;
    readonly height: number;
    readonly renderMode: R;
    children: Renderable[];
    element: HTMLCanvasElement | SVGElement;
    ctx?: CanvasRenderingContext2D;
    static create<R extends RenderMode>(width: number, height?: number, renderMode?: RenderMode): Canvas<R>;
    static create<R extends RenderMode>(renderMode: RenderMode): Canvas<R>;
    static create(): Canvas<'c2d'>;
    private constructor();
    private setupCanvas;
    setCanvas(this: Canvas<'c2d'>, element: HTMLCanvasElement): void;
    clear(): void;
    private add;
    background(color: Color): void;
    circle(position: ArrayLike<number>, radius: number, options?: Partial<CircleOptions>): Circle;
    circle(x: number, y: number, radius: number, options?: Partial<CircleOptions>): Circle;
    rect(position: ArrayLike<number>, width: number, height: number, options: Partial<RectangleOptions>): Rectangle;
    rect(x: number, y: number, width: number, height: number, options?: Partial<RectangleOptions>): Rectangle;
    /**
     * Create a canvas image from `src` at a location scaled to `width` and `height`
     *
     * @param src Image source (URL, base64, or ImageData)
     * @param x X position (defaults to 0)
     * @param y Y position (defaults to 0)
     * @param width Image width (defaults to original image width)
     * @param height Image height (defaults to original image height)
     * @param imageOptions Additional image rendering options
     *
     * @example
     * ```ts
     * const canvas = Canvas.create()
     * await canvas.image("data:image/png;base64,iVBORw0...", 0, 0, 200, 200)
     * ```
     */
    image(src: string | ImageData_2, x?: number, y?: number, width?: number, height?: number, imageOptions?: Partial<ImageOptions>): Promise<Image_2>;
    arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean, options?: Partial<ArcOptions>): Arc;
    /**
     * A path made up of segments by sets of points with different drawing options
     *
     * Example:
     * ```typescript
     * const canvas = Canvas.create()
     * const path = canvas.path()
     *   .strokeWidth(2)        // First segment will have width 2
     *   .add(0, 0).add(10, 10) // Add points to first segment
     *   .strokeWidth(5)        // Creates new segment with width 5
     *   .add(20, 5).add(30, 15) // Add points to second segment
     *   .smooth(true)          // Creates new segment with smooth curves
     *   .add(40, 10).add(50, 20) // Add points to third segment
     * ```
     */
    path(options?: Partial<PathOptions>): Path;
    text(value: string, position: ArrayLike<number>, options?: Partial<TextOptions>): Text_2;
    text(value: string, x: number, y: number, options?: Partial<TextOptions>): Text_2;
    /** Draw to canvas */
    draw(): void;
    /** Returns bounds [xmin, xmax, ymin, ymax] */
    bounds(): FlatBounds<2>;
    html(): SVGElement | HTMLCanvasElement;
}

/**
 * Returns an implementation-dependent approximation to the cube root of number.
 * @param x A numeric expression.
 */
declare function cbrt(x: number): number;

/**
 * Returns the smallest integer greater than or equal to its numeric argument.
 * @param x A numeric expression.
 */
declare function ceil(x: number): number;

declare class Circle extends Geometry {
    x: number;
    y: number;
    radius: number;
    constructor(x: number, y: number, radius: number, opts: CircleOptions);
    _svg(): SVGCircleElement;
    _canvas(ctx: CanvasRenderingContext2D): void;
}

export declare type CircleOptions = GeometricOptions;

/**
 * Returns the number of leading zero bits in the 32-bit binary representation of a number.
 * @param x A numeric expression.
 */
declare function clz32(x: number): number;

export declare class Color extends Uint8Vector<4> {
    static fromHex(hex: string): Color;
    static readonly BLACK: Color;
    static readonly WHITE: Color;
    static readonly RED: Color;
    static readonly GREEN: Color;
    static readonly BLUE: Color;
    static readonly YELLOW: Color;
    static readonly CYAN: Color;
    static readonly MAGENTA: Color;
    static readonly ORANGE: Color;
    static readonly PURPLE: Color;
    static readonly PINK: Color;
    static random(): Color;
    /** Check if a number is within `limits` */
    within(bounds: FlatBounds<4>): boolean;
    /** if a number is above or below a limit it correct it so it is within the boundary limits */
    wrapAround(bounds: FlatBounds<4> | []): this;
    static create(grey: number, a?: number): Color;
    static create(r: number, g: number, b: number, a?: number): Color;
    static create(color: number[] | Uint8ClampedArray | number): Color;
    private constructor();
    private withinBoundsCheck;
    get r(): number;
    set r(v: number);
    get g(): number;
    set g(v: number);
    get b(): number;
    set b(v: number);
    get a(): number;
    set a(v: number);
    mix(color: Color): Color;
    clone(): this;
    scale(s: number): this;
    normalize(): this;
    add(color: Color): this;
    gradient(color: Color, percentage: number): this;
    /**
     * Return the relative luminance value https://en.wikipedia.org/wiki/Relative_luminance
     * a floating point value between 0-255
     * */
    luminance(): number;
    rgb(): string;
    hex(): string;
    u32(): number;
}

export declare function color(grey: number, a?: number): Color;

export declare function color(r: number, g: number, b: number, a?: number): Color;

export declare function color(color: number[] | Uint8ClampedArray | number): Color;

declare interface Contour {
    points: Point[];
    isHole: boolean;
    /** point of origin with pixel boundary */
    _origin: Point;
    /**
     * bounding box coordinates with pixel boundary
     * [x,y,w,h]
     * */
    _boundingBox: FixedNumberArray<4>;
    _ctableNext: number | null;
}

export declare enum ContourApproximation {
    /** Include all points of the contour */
    None = 0,
    /** Skip points in between the horizontal or verticle direction of two points **/
    Simple = 1
}

export declare interface ContourExtractorOpts {
    /**
     * When `true` skip points in between the horizontal or verticle direction of two points.
     *
     * Otherwise return a list of all points
     * */
    approximation: ContourApproximation;
}

/**
 * Static utility class for converting between different array formats
 * Handles type guards, validation, and efficient conversions
 * */
export declare class Conversion {
    /** Type guard for array-like structures (includes arrays, typed arrays, etc.) */
    static isArrayLike(v: unknown): v is ArrayLike<unknown>;
    /** Type guard for flat numeric arrays (1D) */
    static isFlatNumberArray(v: unknown): v is ArrayLike<number>;
    /** Type guard for nested numeric arrays (2D matrix) */
    static isNestedNumberArray(v: unknown): v is ArrayLike<ArrayLike<number>>;
    /** Type guard for typed arrays (Float32Array, Float64Array, etc.) */
    static isTypedArray(v: unknown): v is ArrayBufferView;
    /** Type guard for plain JavaScript arrays (excludes typed arrays) */
    static isPlainArray(v: unknown): v is unknown[];
    static isVector<N extends number>(v: ArrayLike<number>, dimension: N): v is VectorLike<N>;
    /**
     * Convert any array-like structure to Float64Array
     * Handles both flat and nested input formats
     * */
    static toFloat64Array(array: ArrayLike<number>): Float64Array;
    static toFloat64Array(array: ArrayLike<number> | ArrayLike<ArrayLike<number>>, dimension: number): Float64Array;
    /** Convert flat array to Float64Array */
    static flatToFloat64Array(array: ArrayLike<number>): Float64Array;
    /** Convert nested array (matrix) to flat Float64Array */
    static nestedToFloat64Array(array: ArrayLike<ArrayLike<number>>, dimension: number): Float64Array;
    /** Convert flat array to nested array (matrix format) */
    static flatToNested<N extends number>(array: ArrayLike<number>, dimension: N): FixedArray<number, N>[];
    /** Convert ArrayLike<number> to FixedNumberArray<N> */
    static toFixedNumberArray<N extends number>(array: ArrayLike<number>, dimension: N): FixedNumberArray<N>;
    /**
     * Convert ArrayLike or nested ArrayLike to Vector<N>[] with given dimension
     * Supports both flat arrays (chunked by dimension) and nested arrays
     */
    static toVectorArray<N extends number>(array: ArrayLike<number>, dimension: N): Vector<N>[];
    static toVectorArray<N extends number>(array: ArrayLike<ArrayLike<number>>, dimension: N): Vector<N>[];
    /** Convert various formats to flat bounds array [min1, max1, min2, max2, ...] */
    static toBounds<N extends number>(bounds: FlatBounds<N> | FixedArray<[number, number], N>): FlatBounds<N>;
}

/**
 * Returns the cosine of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function cos(x: number): number;

/**
 * Returns the hyperbolic cosine of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function cosh(x: number): number;

/** Factory function for creating a vector type with a given base class. */
export declare function createVectorType<TArray extends MutableNumberArrayLike<number>>(Base: VectorArrayConstructor<TArray>): VectorBaseConstructor;

/** Array of diagonal direction vectors South-East, South-West, North-West, North-East */
export declare const DIAGONALS: Vector<2>[];

/**
 * Get the absolute difference between two numbers
 * @param x First number
 * @param y Second number
 */
declare function diff(x: number, y: number): number;

/** Array of direction vectors East, South, West, North */
export declare const DIRECTIONS: Vector<2>[];

/** Run a draw loop that runs `fn` every 1/60 seconds */
export declare function draw(fn: DrawFn): void;

export declare type DrawFn = (
/** Total running time since page load, as a high precision timestamp */
t: DOMHighResTimeStamp, 
/** Delta time in ms, by default draw is rendering at 60fps so dt should be around 1/60 s = 16.666666667 ms */
dt: number) => void;

/** The mathematical constant e. This is Euler's number, the base of natural logarithms. */
declare const E: number;

/**
 * Returns e (the base of natural logarithms) raised to a power.
 * @param x A numeric expression representing the power of e.
 */
declare function exp(x: number): number;

/**
 * Returns the result of (e^x - 1), which is an implementation-dependent approximation to
 * subtracting 1 from the exponential function of x (e raised to the power of x, where e
 * is the base of the natural logarithms).
 * @param x A numeric expression.
 */
declare function expm1(x: number): number;

export declare type Feature = MeydaAudioFeature | 'bpm';

export declare type FeatureResult = Partial<MeydaFeaturesObject> & {
    bpm?: number;
};

export declare type FixedArray<T, N extends number> = GrowToSize<T, N, [], 0> & T[];

export declare type FixedFloat64Array<N extends number> = Float64Array & {
    length: N;
};

export declare type FixedNumberArray<N extends number> = GrowToSize<number, N, [], 0> & number[];

/** Type for flat bounds array: [min1, max1, min2, max2, ..., minN, maxN] */
export declare type FlatBounds<N extends number> = FixedArray<number, Multiply2<N>>;

export declare class Float32Vector<N extends number> extends Float32VectorBase<N> {
}

export declare interface Float32Vector<N extends number> extends Omit<Float32Array, 'length'> {
}

declare const Float32VectorBase: VectorBaseConstructor;

export declare class Float64Vector<N extends number> extends Float64VectorBase<N> {
}

export declare interface Float64Vector<N extends number> extends Omit<Float64Array, 'length'> {
}

declare const Float64VectorBase: VectorBaseConstructor;

/**
 * Returns the greatest integer less than or equal to its numeric argument.
 * @param x A numeric expression.
 */
declare function floor(x: number): number;

/**
 * Returns the nearest single precision float representation of a number.
 * @param x A numeric expression.
 */
declare function fround(x: number): number;

/**
 * Return the greatest common divisor
 */
declare function gcd(x: number, y: number): number;

declare interface GeometricOptions {
    fill: Color | null;
    fillOpacity: number;
    stroke: Color;
    strokeWidth: number;
    rotation: number;
}

declare abstract class Geometry<Opts extends GeometricOptions = GeometricOptions> extends Renderable {
    options: Opts;
    constructor(opts: Opts);
    strokeWidth(width: number): this;
    /**
     * Set stroke color for the path
     */
    stroke(color: Color): this;
    /**
     * Set fill color for the path
     */
    fill(color: Color | null): this;
    /**
     * Set fill opacity for the path
     */
    fillOpacity(opacity: number): this;
    /**
     * Set rotation angle in radians
     */
    rotate(angle: number): this;
    _applySvgOptions(element: SVGElement): void;
    _applyCanvasOptions(ctx: CanvasRenderingContext2D, path?: Path2D): void;
}

export declare function getHeight(): number;

export declare function getWidth(): number;

declare type GrowToSize<T, N extends number, A extends T[], L extends number = A['length']> = L extends N ? A : L extends 999 ? T[] : GrowToSize<T, N, [...A, T]>;

/**
 * Returns the square root of the sum of squares of its arguments.
 * @param values Values to compute the square root for.
 *     If no arguments are passed, the result is +0.
 *     If there is only one argument, the result is the absolute value.
 *     If any argument is +Infinity or -Infinity, the result is +Infinity.
 *     If any argument is NaN, the result is NaN.
 *     If all arguments are either +0 or −0, the result is +0.
 */
declare function hypot(...values: number[]): number;

declare class Image_2 extends Renderable {
    private readonly img;
    x: number;
    y: number;
    width: number;
    height: number;
    constructor(img: ImageData_2, x: number, y: number, width: number, height: number, _options: ImageOptions);
    data(): ImageData_2;
    _svg(): SVGCircleElement;
    _canvas(ctx: CanvasRenderingContext2D): void;
}

declare class ImageData_2 {
    img: HTMLImageElement;
    readonly cv: OpenCVModule;
    private pixeldata;
    private mat;
    static create(src: string): Promise<ImageData_2>;
    /** @param src url or base64 string with image data */
    private constructor();
    private updatePixeldata;
    get width(): number;
    get height(): number;
    /** Get the count of amount of pixels (rgba values) in Image */
    get pixelCount(): number;
    clone(): ImageData_2;
    /** Convert an index to the Uint8ClampedArray pixel array to coordinates in the image, top left corner being [0,0]  */
    indexToCoords(i: number): [number, number];
    get(x: number, y: number): Color;
    get(p: Vector<2>): Color;
    /**
     * Get a section of the image as `Uint8ClampedArray[]` for efficient representation
     *
     * Gives all pixels in between two points
     * */
    get(x: number, y: number, x2: number, y2: number): Uint8ClampedArray[];
    /**
     * Get a section of the image as `Uint8ClampedArray[]` for efficient representation
     *
     * Gives all pixels in between two points
     * */
    get(p: Vector<2>, p2: Vector<2>): Uint8ClampedArray[];
    html(): Promise<HTMLImageElement>;
    /**
     * Iterate over each pixel in the image
     * @param callback Function called for each pixel with (color, x, y, index)
     */
    forEach(callback: (color: Color, startIndex: number) => void): ImageData_2;
    /**
     * Convert image to bitmap based on luminance threshold
     * @param threshold Luminance threshold value (min: 0, max: 255, default: 255, pixels above threshold become white)
     */
    toBitmap(threshold?: number): Bitmap;
    /**
     * Scale (resize) the image
     * @param factor Scale factor (e.g., 2 = double size, 0.5 = half size) OR target width
     * @param height Optional target height (if first param is width). If omitted and factor is provided, scales proportionally
     * @param interpolation OpenCV interpolation method (default: cv.INTER_LINEAR)
     * @returns The modified ImageData instance
     */
    scale(factor: number, height?: number, interpolation?: number): ImageData_2;
    /**
     * Adjust brightness of the image
     * @param percentage Brightness multiplier (min: 0, max: 3.0, default: 1.0 = no change, >1.0 = brighter, <1.0 = darker)
     */
    brightness(percentage: number): ImageData_2;
    /**
     * Apply horizontal gradient to the image
     * @param startPercentage Starting brightness factor at top (min: 0, max: 1.0)
     * @param endPercentage Ending brightness factor at bottom (min: 0, max: 1.0)
     */
    horizontalGradient(startPercentage: number, endPercentage: number): ImageData_2;
    greyscale(): ImageData_2;
    /**
     * Apply contrast to image making color tend toward middle gray (128)
     * or more towards the outer ends (0, 255)
     *
     * @param factor Contrast multiplier (min: 0.1, max: 3.0, default: 1.0 = no change, >1.0 = increased contrast, <1.0 = decreased contrast)
     */
    contrast(factor: number): ImageData_2;
    /**
     * Invert the colors of the image (negative effect)
     * Each RGB channel is inverted: newValue = 255 - oldValue
     */
    invert(): ImageData_2;
    /**
     * Apply Gaussian blur to the image
     * @param kernelSize Size of the Gaussian kernel (min: 1, typical: 3-15, default: 5, must be odd, will be adjusted if even)
     * @param sigma Standard deviation of the Gaussian kernel (min: 0, default: 0, 0 = auto-calculated from kernel size)
     */
    blur(kernelSize?: number, sigma?: number): ImageData_2;
    /**
     * Apply Sobel edge detection to the image
     * @param dx Order of derivative in x direction (0, 1, or 2, default: 1)
     * @param dy Order of derivative in y direction (0, 1, or 2, default: 1)
     * @param kernelSize Size of the Sobel kernel (1, 3, 5, or 7, default: 3)
     * @returns The modified ImageData instance
     * @see https://docs.opencv.org/4.x/d4/d86/group__imgproc__filter.html#gacea54f142e81b6758cb6f375ce782c8d
     */
    sobel(dx?: number, dy?: number, kernelSize?: number): ImageData_2;
    /**
     * Apply threshold to create a binary image
     * @param threshold Threshold value (min: 0, max: 255, default: 127)
     * @param type Threshold type (default: ThresholdType.BINARY, see ThresholdType enum)
     */
    threshold(threshold?: number, type?: ThresholdType): ImageData_2;
    /**
     * Apply Canny edge detection
     * @param lowThreshold Lower threshold for edge detection (min: 0, max: 255, typical: 50-100, default: 50)
     * @param highThreshold Upper threshold for edge detection (min: 0, max: 255, typical: 100-200, default: 150, should be 2-3x lowThreshold)
     */
    canny(lowThreshold?: number, highThreshold?: number): ImageData_2;
    /**
     * Apply morphological operations (erode, dilate, open, close)
     * @param operation Operation type (default: MorphologyOperation.CLOSE, see MorphologyOperation enum)
     * @param kernelSize Size of the structuring element (min: 1, typical: 3-9, default: 5)
     * @param shape Shape of the structuring element (default: MorphologyShape.ELLIPSE, see MorphologyShape enum)
     */
    morphology(operation?: MorphologyOperation, kernelSize?: number, shape?: MorphologyShape): ImageData_2;
    /**
     * Sharpen the image using unsharp masking
     * @param amount Amount of sharpening (min: 0, typical: 0.5-2.5, default: 1.5, higher = more sharpening)
     */
    sharpen(amount?: number): ImageData_2;
    /**
     * Apply adaptive threshold (good for images with varying lighting)
     * @param blockSize Size of pixel neighborhood (min: 3, typical: 5-21, default: 11, must be odd, will be adjusted if even)
     * @param C Constant subtracted from the mean (typical: -10 to 10, default: 2, positive = darker threshold, negative = lighter threshold)
     */
    adaptiveThreshold(blockSize?: number, C?: number): ImageData_2;
    /**
     * Extract smoothed line contours from the image
     * @param blurSize Gaussian blur kernel size for pre-smoothing (min: 0, typical: 3-9, default: 5, 0 = no blur, must be odd)
     * @param morphSize Morphological operation size to clean up noise (min: 0, typical: 2-5, default: 3, 0 = skip)
     * @param epsilon Curve approximation accuracy (min: 0, typical: 0.5-3, default: 0.5, lower = more detail, 0 = no approximation, pixels)
     * @param threshold Binary threshold value (min: 0, max: 255, typical: 100-150, default: 120)
     */
    lines(blurSize?: number, morphSize?: number, epsilon?: number, threshold?: number): Vector<2>[][];
    potrace(): void;
}
export { ImageData_2 as ImageData }

export declare type ImageOptions = object;

/**
 * Returns the result of 32-bit multiplication of two numbers.
 * @param x First number
 * @param y Second number
 */
declare function imul(x: number, y: number): number;

export declare class Int16Vector<N extends number> extends Int16VectorBase<N> {
}

export declare interface Int16Vector<N extends number> extends Omit<Int16Array, 'length'> {
}

declare const Int16VectorBase: VectorBaseConstructor;

export declare class Int32Vector<N extends number> extends Int32VectorBase<N> {
}

export declare interface Int32Vector<N extends number> extends Omit<Int32Array, 'length'> {
}

declare const Int32VectorBase: VectorBaseConstructor;

export declare class Int8Vector<N extends number> extends Int8VectorBase<N> {
}

export declare interface Int8Vector<N extends number> extends Omit<Int8Array, 'length'> {
}

declare const Int8VectorBase: VectorBaseConstructor;

export declare function isVector<N extends number = number>(value: unknown): value is VectorLike<N>;

/**
 * A wrapper class for iterables that provides chainable iterator operations
 */
export declare class Iter<T> implements Iterable<T> {
    private readonly iterable;
    constructor(iterable: Iterable<T>);
    /** Make the class itself iterable */
    [Symbol.iterator](): Iterator<T>;
    /** Create an Iter from a range of numbers */
    static range(start: number, stop?: number): Iter<number>;
    static range(stop: number): Iter<number>;
    /** Create an Iter from any iterable */
    static from<T>(iterable: Iterable<T>): Iter<T>;
    enumerate(): Iter<[number, T]>;
    /** Split the iterable into chunks of specified size */
    chunk(chunkSize: number): Iter<T[]>;
    /** Randomize the order of items */
    randomize(length: number, randomFn?: UnitRandomFn): Iter<T>;
    /** Map each item to a new value */
    map<U>(fn: (item: T, index: number) => U): Iter<U>;
    /** Filter items based on a predicate */
    filter(fn: (item: T, index: number) => boolean): Iter<T>;
    /** Find the index of the first item that matches the predicate */
    findIndex(fn: (item: T, index: number) => boolean): number;
    /** Reduce the iterable to a single value */
    reduce<U>(fn: (acc: U, item: T, index: number) => U, initial: U): U;
    /** Convert to array */
    toArray(): T[];
    /** Get the first item, or undefined if empty */
    first(): T | undefined;
    /** Count the number of items */
    count(): number;
}

declare interface Iterator_2<V> {
    ids: Int32Array;
    size: number;
    [Symbol.iterator]: () => {
        next: () => {
            value: V;
            done: boolean;
        };
    };
}

export declare class KDTree {
    tree: default_2;
    constructor(length: number);
    constructor(dataset: Vector<2>[]);
    insert(point: Vector<2>): void;
    finish(): void;
    nearest(point: Vector<2>, maxDistance: number): number[];
}

export declare class KMeans<N extends number, K extends number> {
    private readonly _clusters;
    private readonly _centroids;
    static create<N extends number>(vectors: Vector<N>[], k: number): KMeans<N, number>;
    constructor(vectors: Vector<N>[], k: K);
    clusters(): number[];
    centroids(): FixedArray<number, N>[];
}

/** Linear interpolation between two values, given a factor `t` between 0 and 1 */
declare function lerp(a: number, b: number, t: number): number;

/** The natural logarithm of 10. */
declare const LN10: number;

/** The natural logarithm of 2. */
declare const LN2: number;

/** Load a html loadable object into #canvas-container */
export declare function load(loadableObject: LoadableObject): Promise<void>;

export declare type LoadableObject = Node | {
    html: () => Node;
} | {
    html: () => Promise<Node>;
};

/**
 * Returns the natural logarithm (base e) of a number.
 * @param x A numeric expression.
 */
declare function log(x: number): number;

/**
 * Returns the base 10 logarithm of a number.
 * @param x A numeric expression.
 */
declare function log10(x: number): number;

/** The base-10 logarithm of e. */
declare const LOG10E: number;

/**
 * Returns the natural logarithm of 1 + x.
 * @param x A numeric expression.
 */
declare function log1p(x: number): number;

/**
 * Returns the base 2 logarithm of a number.
 * @param x A numeric expression.
 */
declare function log2(x: number): number;

/** The base-2 logarithm of e. */
declare const LOG2E: number;

export declare namespace Math {
    export {
        lerp,
        gcd,
        mod,
        roundToDec,
        diff,
        clz32,
        imul,
        sign,
        log10,
        log2,
        log1p,
        expm1,
        cosh,
        sinh,
        tanh,
        acosh,
        asinh,
        atanh,
        hypot,
        trunc,
        fround,
        cbrt,
        abs,
        acos,
        asin,
        atan,
        atan2,
        ceil,
        cos,
        exp,
        floor,
        log,
        max,
        min,
        pow,
        random,
        round,
        sin,
        sqrt,
        tan,
        E,
        LN10,
        LN2,
        LOG2E,
        LOG10E,
        PI,
        SQRT1_2,
        SQRT2
    }
}

export declare class Matrix<R extends number, C extends number> {
    readonly rows: R;
    readonly cols: C;
    private elements;
    static identity<R extends number>(size: R): Matrix<R, R>;
    static empty<R extends number, C extends number>(rows: R, cols: C): Matrix<R, C>;
    static create<R extends number, C extends number>(elements: number[], rows: R, cols: C): Matrix<R, C>;
    constructor(elements: number[], rows: R, cols: C);
    constructor(...rows: (number[] & {
        length: C;
    })[] & {
        length: R;
    });
    constructor(rows: (number[] & {
        length: C;
    })[] & {
        length: R;
    });
    get length(): number;
    /** Return a copy of the row vector */
    get(row: number): Vector<C>;
    /** Get a value of the matrix */
    get(row: number, col: number): number;
    set(row: number, col: number, value: number): void;
    col(col: number): Generator<number, this>;
    clone(): Matrix<R, C>;
    /** https://en.wikipedia.org/wiki/Determinant */
    determinant(): number;
    /** Multiply diagonal of matrix */
    diag(): number;
    swapRows(i: number, j: number): this;
    roundToDec(decimal: number): this;
    /**
     * [LU factorization with partial pivoting](https://en.wikipedia.org/wiki/LU_decomposition#LU_factorization_with_partial_pivoting)
     *
     * Returns [L, U, P] such that PA = LU
     * */
    lup(): [Matrix<R, R>, Matrix<R, R>, Matrix<R, R>];
    /** Create a string representation of this matrix */
    toString(): string;
}

export declare function matrix(): void;

/**
 * Returns the larger of a set of supplied numeric expressions.
 * @param values Numeric expressions to be evaluated.
 */
declare function max(...values: number[]): number;

/**
 * Returns the smaller of a set of supplied numeric expressions.
 * @param values Numeric expressions to be evaluated.
 */
declare function min(...values: number[]): number;

/**
 * Proper modulo that also handles negative cases
 */
declare function mod(x: number, y: number): number;

/**
 * Morphological operations for image processing
 * @see https://docs.opencv.org/4.x/d9/d61/tutorial_py_morphological_ops.html
 */
export declare enum MorphologyOperation {
    /** Erode - shrinks bright regions, removes small white noise */
    ERODE = 0,
    /** Dilate - expands bright regions, fills small holes */
    DILATE = 1,
    /** Opening - erosion followed by dilation, removes small bright noise while preserving shape */
    OPEN = 2,
    /** Closing - dilation followed by erosion, fills small dark holes while preserving shape */
    CLOSE = 3,
    /** Morphological gradient - difference between dilation and erosion, outlines objects */
    GRADIENT = 4,
    /** Top hat - difference between input and opening, extracts small bright elements */
    TOPHAT = 5,
    /** Black hat - difference between closing and input, extracts small dark elements */
    BLACKHAT = 6,
    /** Hit-or-miss transform - finds specific patterns in binary images */
    HITMISS = 7
}

/**
 * Structuring element shapes for morphological operations
 */
export declare enum MorphologyShape {
    /** Rectangular structuring element */
    RECT = 0,
    /** Cross-shaped structuring element (+ shape) */
    CROSS = 1,
    /** Elliptical/circular structuring element (smoothest) */
    ELLIPSE = 2
}

declare type Multiply2<N extends number> = [
...Tuple<N>,
...Tuple<N>
]['length'] extends number ? [...Tuple<N>, ...Tuple<N>]['length'] : never;

declare type MutableNumberArrayLike<N extends number = number> = NumberArrayLike<N> & {
    [index: number]: number;
};

/** Branded type for tree node IDs - can only be created by Tree.new() */
export declare type NodeId<T = unknown> = number & {
    readonly __brand: 'NodeId';
    readonly __tree: T;
};

/** Any array-like numeric sequence (regular arrays and typed arrays) */
declare type NumberArray = ArrayLike<number> & Iterable<number>;

declare type NumberArrayLike<N extends number = number> = ArrayLike<number> & {
    length: N;
};

declare type OpenCVModule = CV;

declare class Path extends Geometry<PathOptions> {
    private readonly _segments;
    /** Reference to current segment */
    currentPoints: Vector<2>[];
    constructor(options: PathOptions);
    /** Create a new path segment with a set of options */
    private newSegment;
    strokeWidth(width: number): this;
    /**
     * Set stroke color for the path
     */
    stroke(color: Color): this;
    /**
     * Set fill color for the path
     */
    fill(color: Color | null): this;
    /**
     * Set fill opacity for the path
     */
    fillOpacity(opacity: number): this;
    /**
     * Set smooth option for the path
     * @param tension Control curve tension (0.0-1.0): higher values make sharper curves, by default smooth (0)
     */
    smooth(tension?: number): this;
    /**
     * Set whether the path should be closed (connect first and last points)
     */
    closed(closed?: boolean): this;
    /**
     * Set wrap around bounds for the path
     */
    wrapAround(bounds: FlatBounds<2> | null): this;
    /** Get information about current segments (for debugging) */
    segments(): ReadonlyArray<Readonly<PathSegment>>;
    /** Get all points in the path */
    points(): Vector<2>[];
    /** Get total number of points across all segments */
    size(): number;
    /** TODO: https://github.com/xaviergonz/js-angusj-clipper */
    add(points: ArrayLike<number>[]): this;
    add(v: ArrayLike<number>): this;
    add(x: number, y: number): this;
    _svg(): SVGPathElement | SVGGElement;
    _canvas(ctx: CanvasRenderingContext2D): void;
}

export declare interface PathOptions extends GeometricOptions {
    /** Connect the first point with the last point */
    closed: boolean;
    /** Wrap the path around a certain bound */
    wrapAround: FlatBounds<2> | null;
    /** Control curve tension (0.0-1.0): higher values make sharper curves */
    tension: number;
}

declare interface PathSegment {
    points: Vector<2>[];
    options: PathOptions;
}

/** Pi. This is the ratio of the circumference of a circle to its diameter. */
declare const PI: number;

declare type Point = [number, number];

/**
 * A set of points in N dimensional space
 *
 * uses a `Float64Array` internally to store points
 */
export declare class PointCloud<N extends number> {
    private points;
    private readonly dimensions;
    _delaunay?: Delaunay;
    _voronoi?: Voronoi;
    /**
     * Generate a set of points where each point has a minimum distance `minimumDistance` from any other point filling up the space within `bounds`
     *
     * This uses a modified version of [Bridson's Algorithm](https://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf)
     * , [visualized](https://observablehq.com/@techsparx/an-improvement-on-bridsons-algorithm-for-poisson-disc-samp/2)
     * */
    static poissonRandomDiskSampling(minimumDistance: number, bounds: FlatBounds<2>): PointCloud<2>;
    static randomFloatSampling<N extends number = 2>(
    /** Amount of random points to generate */
    amount: number, bounds: FlatBounds<N>, // [min1, max1, min2, max2, ...]
    dimension?: N, 
    /** return a number between 0-1 for the probability it gets added given a coordinate */
    samplingDistribution?: (...coords: FixedArray<number, N>) => number): PointCloud<N>;
    static randomIntegerSampling<N extends number = 2>(
    /** Amount of random points to generate */
    amount: number, bounds: FlatBounds<N>, // [min1, max1, min2, max2, ...] - bounds will be floored/ceiled to integers
    dimension?: N, 
    /** return a number between 0-1 for the probability it gets added given a coordinate */
    samplingDistribution?: (...coords: FixedArray<number, N>) => number): PointCloud<N>;
    static grid<N extends number = 2>(
    /** Number of points per dimension */
    counts: number | FixedNumberArray<N>, 
    /** [min1, max1, min2, max2, ...] */
    bounds: FlatBounds<N>, dimension?: N): PointCloud<N>;
    static create<N extends number = 2>(points: ArrayLike<number> | ArrayLike<ArrayLike<number>> | Float64Array, dimension?: N): PointCloud<N>;
    /** Returns the amount of points in the point cloud */
    readonly size: number;
    private constructor();
    /**
     * Iterator implementation - allows for...of loops over points
     */
    [Symbol.iterator](): Iterator<FixedFloat64Array<N>>;
    private clearCache;
    /** Set a point at a specfic index */
    setPoint(index: number, point: FixedArray<number, N>): void;
    /** Get a specific point by index */
    at(index: number): FixedFloat64Array<N>;
    /**
     * Returns an array of all points
     */
    toArray(): FixedFloat64Array<N>[];
    /**
     * Filters points based on a predicate function and returns a new PointCloud
     */
    filter(predicate: (point: FixedFloat64Array<N>, index: number) => boolean): PointCloud<N>;
    /**
     * Applies a transformation to each point in place (mutates the current PointCloud)
     * Returns this for method chaining
     */
    transform(callback: (point: FixedFloat64Array<N>, index: number) => FixedArray<number, N>): this;
    delaunay(): Delaunay;
    voronoi(bounds: FlatBounds<2>): Voronoi;
    /**
     * [Lloyd's Algorithm (Voronoi Relaxation)](https://en.wikipedia.org/wiki/Lloyd%27s_algorithm)
     *
     * Iteratively moves each point to the centroid of its Voronoi cell to create
     * a more uniform distribution. This requires bounds to be specified.
     *
     * @param bounds [xmin, ymin, xmax, ymax] - The bounds for the point cloud
     * @param iterations Number of Lloyd iterations to perform (default: 1)
     * @param tolerance When average movement per iteration is lower than this amount it will stop iterating if `undefined` it is calculated based on boundary size
     * @param weight Make it weighted, giving a certain bias towards certain values, this is basically [Voronoi Weighted Stippling](https://www.cs.ubc.ca/labs/imager/tr/2002/secord2002b/secord.2002b.pdf) when used with a random sampling technique like [Rejection Sampling](https://en.wikipedia.org/wiki/Rejection_sampling) for getting points on darker/lighter parts of an image @returns a number between 0-1 giving the weight of that point
     *
     * @returns The updated points array
     */
    lloyd(this: PointCloud<2>, bounds: FlatBounds<2>, iterations?: number, tolerance?: number, weight?: (x: number, y: number) => number): PointCloud<2>;
}

/** Any array-like iterable collection of {@link NumberArray} elements */
declare type PositionArray = ArrayLike<NumberArray> & Iterable<NumberArray>;

/**
 * Returns the value of a base expression taken to a specified power.
 * @param x The base value of the expression.
 * @param y The exponent value of the expression.
 */
declare function pow(x: number, y: number): number;

export declare class QuadTree {
    points: FixedNumberArray<2>[];
    tree: Quadtree<FixedNumberArray<2>>;
    constructor(points: FixedNumberArray<2>[]);
    nearest(index: number, radius?: number): FixedNumberArray<2> | undefined;
}

/**
 * Random namespace
 *
 * Generate random numbers using different distributions and generators
 *
 * Random number generating functions with a range between 0 and 1 will return their own random number generator
 */
export declare class Random {
    /** generate a random number until and including `stop` */
    static integer(stop: number): number;
    static integer(start: number, stop: number): number;
    static float(): number;
    static float(stop: number): number;
    static float(start: number, stop: number): number;
    static simplex(x: number, y: number): number;
    static simplex(x: number, y: number, z: number): number;
    static simplex(x: number, y: number, z: number, w: number): number;
    /**
     * Generate a smooth continuous number between -1 and 1 using [Perlin Noise](https://en.wikipedia.org/wiki/Perlin_noise) given a 3d coordinate.
     *
     * NOTE: It will return 0 for integer values in order to ensure continuity
     * */
    static perlin(x: number, y: number, z: number): number;
    static bool(p?: number): boolean;
    static xorshift(seed?: number): RandomNumberGenerator;
    /** https://en.wikipedia.org/wiki/Beta_distribution */
    static beta(alpha: number, beta: number, uniformGenerator?: UnitRandomFn): RandomNumberGenerator;
    /** Normally distributed Random Number Generator using [Box Muller](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) */
    static boxMuller(mean: number, deviation: number, uniformGenerator?: UnitRandomFn): RandomNumberGenerator;
    /** Exponentially distributed random number https://en.wikipedia.org/wiki/Exponential_distribution bounded to never exceed 1*/
    static truncatedExponential(lambda: number, uniformGenerator?: RandomFn): RandomNumberGenerator;
    /** Normally distributed Random Number Generator using [Box Muller](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) */
    static normal(mean: number, deviation: number, uniformGenerator?: UnitRandomFn): RandomFn;
    /** Exponentially distributed random number https://en.wikipedia.org/wiki/Exponential_distribution */
    static exponential(lambda: number, uniformGenerator?: UnitRandomFn): RandomFn;
}

/** Returns a pseudorandom number between 0 and 1. */
declare function random(): number;

/** A random number generator function */
declare type RandomFn = () => number;

declare class RandomNumberGenerator {
    private readonly randomFn;
    constructor(random: UnitRandomFn);
    /** generate a random number until and including `stop` */
    integer(stop: number): number;
    integer(start: number, stop: number): number;
    float(): number;
    float(stop: number): number;
    float(start: number, stop: number): number;
    bool(p?: number): boolean;
}

declare class Rectangle extends Geometry<RectangleOptions> {
    x: number;
    y: number;
    width: number;
    height: number;
    constructor(x: number, y: number, width: number, height: number, opts: RectangleOptions);
    _svg(): SVGRectElement;
    _canvas(ctx: CanvasRenderingContext2D): void;
}

export declare type RectangleOptions = GeometricOptions;

declare abstract class Renderable {
    abstract _svg(): SVGElement;
    abstract _canvas(ctx: CanvasRenderingContext2D): void;
    _dirty: boolean;
}

/** How the code renders in the browser  */
export declare type RenderMode = 
/** Default 2d rendering format */
'c2d'
/** Svg rendering format */
| 'svg';

/**
 * Returns a supplied numeric expression rounded to the nearest integer.
 * @param x The value to be rounded to the nearest integer.
 */
declare function round(x: number): number;

/**
 * Round number to a `dec` decimal point
 */
declare function roundToDec(n: number, dec?: number): number;

/**
 * Returns the sign of the x, indicating whether x is positive, negative or zero.
 * @param x The numeric expression to test
 */
declare function sign(x: number): number;

/**
 * Returns the sine of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function sin(x: number): number;

/**
 * Returns the hyperbolic sine of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function sinh(x: number): number;

/**
 * Spatial map that uses hash mapping for efficiently finding nearest neighbors
 * Inspired by https://github.com/matthias-research/pages/blob/master/tenMinutePhysics/11-hashing.html#L293
 */
export declare class SpatialMap {
    private readonly wrap;
    private cellStart;
    private cellEntries;
    private queryIds;
    private querySize;
    private readonly spacing;
    private positionsSize;
    private readonly positions;
    private readonly width;
    private readonly height;
    private readonly rowLength;
    private readonly columnLength;
    constructor(width: number, height: number, spacing: number, positions: PositionArray, opts?: {
        /** Make the space [toroidal](https://en.wikipedia.org/wiki/Torus). Left wraps around to the right and top wraps around to the bottom */
        wrap: boolean;
    });
    /** Update the spatial map with changed positions */
    update(): void;
    /** get the index of a tile from normal cartesian coordiantes */
    getIndex(pos: NumberArray): number;
    /** get the index of a tile given row and column wrapping if it is outside of range */
    get(i: number, j: number): number;
    /** get top left corner of square used */
    coordsFromIndex(index: number): [number, number];
    /**
     * Strictly all nearest neighbors within a distance
     * returns an iterator with [index of position, direction, distance^2]
     * */
    nearestNeighbors(i: number | NumberArray, distance: number): Iterator_2<[number, [number, number], number]>;
    /**
     * all nearest neighbor within the spacing of the grid (might be outside distance),
     *
     * returns an iterator with all the ids
     * */
    nearestNeighborsFromGrid(i: number | NumberArray, distance: number): Iterator_2<number>;
}

/**
 * Returns the square root of a number.
 * @param x A numeric expression.
 */
declare function sqrt(x: number): number;

/** The square root of 0.5, or, equivalently, one divided by the square root of 2. */
declare const SQRT1_2: number;

/** The square root of 2. */
declare const SQRT2: number;

/**
 * Helper type for static vector factory methods.
 * Strips the dimension-dependent VectorMethods interface and re-applies it with the correct dimension.
 * This preserves the base vector type (Vector, Float32Vector, etc.) while fixing the dimension.
 *
 * @example
 * ```ts
 * // polar returns 2D vectors
 * const v1: StaticVectorResult<Vector<number>, 2> = Vector.polar(1, 0)
 * // Equivalent to: Vector<2>
 *
 * // linSpace returns vectors with the specified dimension
 * const v2: StaticVectorResult<Float32Vector<number>, 5> = Float32Vector.linSpace(0, 10, 5)
 * // Equivalent to: Float32Vector<5>
 * ```
 */
declare type StaticVectorResult<TVector extends VectorMethods<number>, N extends number> = Omit<TVector, keyof VectorMethods<number>> & VectorMethods<N>;

/**
 * Returns the tangent of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function tan(x: number): number;

/**
 * Returns the hyperbolic tangent of a number.
 * @param x A numeric expression that contains an angle measured in radians.
 */
declare function tanh(x: number): number;

declare class Text_2 extends Geometry<TextOptions> {
    x: number;
    y: number;
    value: string;
    constructor(x: number, y: number, value: string, options: TextOptions);
    text(value: string): this;
    fontFamily(value: string): this;
    fontSize(value: number): this;
    fontStyle(value: string): this;
    fontWeight(value: string): this;
    textAlign(value: CanvasTextAlign): this;
    textBaseline(value: CanvasTextBaseline): this;
    maxWidth(value: number | null): this;
    lineHeight(value: number): this;
    _svg(): SVGTextElement;
    _canvas(ctx: CanvasRenderingContext2D): void;
}

export declare interface TextOptions extends GeometricOptions {
    fontFamily: string;
    fontSize: number;
    fontStyle: string;
    fontWeight: string;
    textAlign: CanvasTextAlign;
    textBaseline: CanvasTextBaseline;
    maxWidth: number | null;
    lineHeight: number;
}

/**
 * Threshold types for image binarization
 * @see https://docs.opencv.org/4.x/d7/d4d/tutorial_py_thresholding.html
 */
export declare enum ThresholdType {
    /** Binary threshold: pixel > threshold ? 255 : 0 */
    BINARY = 0,
    /** Binary inverse threshold: pixel > threshold ? 0 : 255 */
    BINARY_INV = 1,
    /** Truncate threshold: pixel > threshold ? threshold : pixel (caps values) */
    TRUNC = 2,
    /** To zero threshold: pixel > threshold ? pixel : 0 (removes low values) */
    TOZERO = 3,
    /** To zero inverse threshold: pixel > threshold ? 0 : pixel (removes high values) */
    TOZERO_INV = 4,
    /** Otsu's method: automatically determines optimal threshold using histogram */
    OTSU = 8,
    /** Triangle method: automatically determines threshold using triangle algorithm */
    TRIANGLE = 16
}

export declare class Tree<T> {
    values: Array<T>;
    firstChild: Uint32Array;
    nextSibling: Uint32Array;
    parent: Uint32Array;
    private capacity;
    private size;
    static create<T>(initialCapacity?: number): Tree<T>;
    private constructor();
    private resize;
    new(body: T): NodeId<T>;
    get(id: NodeId<T>): T;
    get(id: number): T;
    getParent(id: NodeId<T>): NodeId<T> | null;
    getParent(id: number): NodeId<T> | null;
    setParent(id: NodeId<T>, parentId: NodeId<T> | null): void;
    setParent(id: number, parentId: NodeId<T> | number | null): void;
    getFirstChild(id: NodeId<T>): NodeId<T> | null;
    getFirstChild(id: number): NodeId<T> | null;
    setFirstChild(id: NodeId<T>, childId: NodeId<T> | null): void;
    setFirstChild(id: number, childId: NodeId<T> | number | null): void;
    getNextSibling(id: NodeId<T>): NodeId<T> | null;
    getNextSibling(id: number): NodeId<T> | null;
    setNextSibling(id: NodeId<T>, siblingId: NodeId<T> | null): void;
    setNextSibling(id: number, siblingId: NodeId<T> | number | null): void;
    getPrevSibling(id: NodeId<T>): NodeId<T> | null;
    getPrevSibling(id: number): NodeId<T> | null;
    addChild(parentId: NodeId<T>, childId: NodeId<T>): void;
    addChild(parentId: number, childId: number): void;
    /**
     * Gets the first root node found in the tree (a node with parent = null)
     * Returns null if no root is found
     */
    getRoot(): NodeId<T> | null;
    /**
     * Gets all root nodes in the tree (nodes with parent = null)
     * Returns an empty array if no roots are found
     */
    getRoots(): NodeId<T>[];
    /**
     * Generator that yields all direct children of a node (in order).
     */
    children(id: NodeId<T> | number): Generator<NodeId<T>, void, void>;
}

/**
 * Returns the integral part of the a numeric expression, x, removing any fractional digits.
 * If x is already an integer, the result is x.
 * @param x A numeric expression.
 */
declare function trunc(x: number): number;

declare type Tuple<N extends number, R extends readonly unknown[] = []> = R['length'] extends N ? R : Tuple<N, readonly [...R, unknown]>;

export declare class Uint16Vector<N extends number> extends Uint16VectorBase<N> {
}

export declare interface Uint16Vector<N extends number> extends Omit<Uint16Array, 'length'> {
}

declare const Uint16VectorBase: VectorBaseConstructor;

export declare class Uint32Vector<N extends number> extends Uint32VectorBase<N> {
}

export declare interface Uint32Vector<N extends number> extends Omit<Uint32Array, 'length'> {
}

declare const Uint32VectorBase: VectorBaseConstructor;

export declare class Uint8ClampedVector<N extends number> extends Uint8ClampedVectorBase<N> {
}

export declare interface Uint8ClampedVector<N extends number> extends Omit<Uint8ClampedArray, 'length'> {
}

declare const Uint8ClampedVectorBase: VectorBaseConstructor;

export declare class Uint8Vector<N extends number> extends Uint8VectorBase<N> {
}

export declare interface Uint8Vector<N extends number> extends Omit<Uint8Array, 'length'> {
}

declare const Uint8VectorBase: VectorBaseConstructor;

/**
 * A random() function, must return a number in the interval [0,1), just like Math.random().
 */
declare type UnitRandomFn = () => number;

/** Create a vector, preserving typed array type when passed */
export declare function vec<N extends number>(...items: [Float32Array & {
    length: N;
}]): Float32Vector<N>;

export declare function vec<N extends number>(...items: [Float64Array & {
    length: N;
}]): Float64Vector<N>;

export declare function vec<N extends number>(...items: [Int8Array & {
    length: N;
}]): Int8Vector<N>;

export declare function vec<N extends number>(...items: [Int16Array & {
    length: N;
}]): Int16Vector<N>;

export declare function vec<N extends number>(...items: [Int32Array & {
    length: N;
}]): Int32Vector<N>;

export declare function vec<N extends number>(...items: [Uint8Array & {
    length: N;
}]): Uint8Vector<N>;

export declare function vec<N extends number>(...items: [Uint8ClampedArray & {
    length: N;
}]): Uint8ClampedVector<N>;

export declare function vec<N extends number>(...items: [Uint16Array & {
    length: N;
}]): Uint16Vector<N>;

export declare function vec<N extends number>(...items: [Uint32Array & {
    length: N;
}]): Uint32Vector<N>;

export declare function vec<N extends number>(...items: [NumberArrayLike<N>]): Vector<N>;

export declare function vec<N extends number>(...items: [...number[]] & {
    length: N;
}): Vector<N>;

export declare function vec<N extends number>(...items: [...number[]]): Vector<N>;

export declare class Vector<N extends number> extends ArrayVectorBase<N> {
}

export declare interface Vector<N extends number> extends Omit<Array<number>, 'length' | 'push'> {
}

declare type VectorArrayConstructor<TArray extends MutableNumberArrayLike<number>> = {
    new (length: number): TArray;
    readonly prototype: TArray;
};

declare type VectorBaseConstructor = {
    new <N extends number>(...items: VectorItems<N>): VectorMethods<N>;
    /** Generate an evenly spaced vector */
    linSpace<TVector extends VectorMethods<number>, N extends number>(this: new (items: ArrayLike<number>) => TVector, start: number, end: number, count: N): StaticVectorResult<TVector, N>;
    empty<TVector extends VectorMethods<number>, N extends number>(this: new (items: ArrayLike<number>) => TVector, length: N): StaticVectorResult<TVector, N>;
    /** https://en.wikipedia.org/wiki/Polar_coordinate_system */
    polar<TVector extends VectorMethods<number>>(this: new (items: ArrayLike<number>) => TVector, radius: number, angle: number): StaticVectorResult<TVector, 2>;
};

declare type VectorInput<N extends number = number> = NumberArrayLike<N>;

declare type VectorItems<N extends number> = [NumberArrayLike<N>] | (number[] & {
    length: N;
}) | number[];

declare type VectorLike<N extends number = number> = VectorStorage<N> & Iterable<number> & {
    readonly x: number;
    readonly y: Y<N>;
    readonly z: Z<N>;
};

/**
 * Full interface of all vector instance methods.
 * Declared explicitly so the `this` return types survive TypeScript's
 * declaration emit (anonymous structural types cannot express `this`).
 */
declare interface VectorMethods<N extends number> {
    [index: number]: number;
    readonly length: N;
    get x(): number;
    set x(v: number);
    get y(): Y<N>;
    set y(v: number);
    get z(): Z<N>;
    set z(v: number);
    push(): number;
    pop(): number | undefined;
    clone(): this;
    /** Squared euclidean distance to another vector */
    dist2(v: VectorInput<N>): number;
    dist(v: VectorInput<N>): number;
    /** mutable mapping of vector values */
    mutmap(callbackfn: (value: number, index: number, array: VectorStorage<N>) => number): this;
    add(v: VectorInput<N>): this;
    /** normalize */
    norm(): this;
    sub(v: VectorInput<N>): this;
    roundToDec(dec?: number): this;
    /** Linear interpolation towards `target` in steps of `alpha`% */
    lerp(target: VectorInput<N>, alpha: number): this;
    /** Randomize the order of the elements inside of the vector */
    randomSort(): this;
    /** Compare two vectors for equality */
    equals(v: VectorInput<N>): boolean;
    dot(v: VectorInput<N>): number;
    /**
     * Treat two vectors as a 2d matrix and get the
     * [determinant](https://en.wikipedia.org/wiki/Determinant) between them.
     */
    det(vector: VectorInput<2>): number;
    /** Apply modulo to each value */
    mod(mod: number): this;
    round(): this;
    /** Divide vector by vector */
    divVector(v: VectorInput<N>): this;
    /** Divide vector */
    div(s: number): this;
    /** Divide each value */
    div(x: number, y: number): this;
    /** Divide each value */
    div(...divisors: FixedArray<number, N>): this;
    /** Scale vector */
    mul(s: number): this;
    /** Multiply each value */
    mul(x: number, y: number): this;
    /** Multiply each value */
    mul(...multipliers: FixedArray<number, N>): this;
    floor(): this;
    scale(s: number): this;
    /** arithmetic mean */
    mean(): number;
    /** arithmetic average */
    average(): number;
    /** magnitude */
    mag(): number;
    /** magnitude squared */
    mag2(): number;
    /** Apply a power to all elements */
    pow(power: number): this;
    /** Calculate the average difference from the average */
    spread(): number;
    /** Calculate the average difference from the average squared */
    spread2(): number;
    chunk<M extends number>(size: M): VectorLike<M>[];
    /** Check if a number is within `limits` */
    within(bounds: FlatBounds<N>): boolean;
    /**
     * Angle between x-axis and ray from origin to [x,y] from -pi to pi
     * https://en.wikipedia.org/wiki/Atan2
     */
    atan2(): number;
    /**
     * Positive atan2 — from 0 to 2pi
     * https://en.wikipedia.org/wiki/Atan2
     */
    atan2p(): number;
    /**
     * Rotate the vector around its zero point
     * @param theta - the angle to rotate in radians
     */
    rotate(theta: number): this;
    rotateLeft(): this;
    rotateRight(): this;
    /** if a number is above or below a limit it corrects it so it is within the boundary limits */
    wrapAround(bounds: FlatBounds<N>): this;
    /** Clamp each dimension to stay within bounds */
    clamp(bounds: FlatBounds<N>): this;
    /** Clamp each dimension to stay within min/max values */
    clampRange(min: number, max: number): this;
    /** Reflect off bounds when hitting them (bouncing behavior) */
    reflect(bounds: FlatBounds<N>): this;
    /** Scale vector to fit within bounds while maintaining proportions */
    fitToBounds(bounds: FlatBounds<N>): this;
    sum(): number;
    compare(vector: VectorInput<N>): boolean;
}

declare type VectorStorage<N extends number = number> = MutableNumberArrayLike<N>;

declare type Y<N extends number> = N extends 3 ? number : N extends 2 ? number : undefined;

declare type Z<N extends number> = N extends 3 ? number : undefined;

export { }
