import type { AnimationAction } from "three";
import { AnimationTree } from "./AnimationTree";
/**
 * Configuration for a polar animation action in the blend tree.
 * Associates an animation action with polar coordinates (radius, azimuth).
 *
 * @public
 */
export interface PolarAction {
    /** The Three.js animation action to be played */
    action: AnimationAction;
    /** Radial distance from the origin. Must be finite and positive. */
    radius: number;
    /** Angular position in radians. Must be finite. Will be normalized to [0, 2π) range. */
    azimuth: number;
}
/**
 * Configuration options for polar blend tree behavior.
 *
 * @public
 */
export interface PolarBlendTreeOptions {
    /** Animation action to play at the center (origin) of the polar space */
    centerAction: AnimationAction;
    /** Whether the blend tree should loop azimuthal blending at 2π */
    isLooped: boolean;
}
/**
 * Polar blend tree implementation for 2D animation blending in polar coordinates.
 *
 * This class manages a collection of animation actions positioned in polar space (radius, azimuth),
 * automatically blending between adjacent animations based on polar coordinates. The blend tree
 * organizes actions into rays (constant azimuth) and rings (constant radius) to enable efficient
 * bilinear interpolation between the four closest animations, creating smooth transitions across
 * the polar space.
 *
 * ## Architecture
 * - **Rays**: Groups of anchors with the same azimuth but different radii
 * - **Rings**: Groups of anchors with the same radius but different azimuths
 * - **Bilinear Interpolation**: Weight calculation between 4 corner anchors in polar grid
 * - **Center Action**: Optional action at origin (0,0) for special handling
 *
 * ## Coordinate System
 * - **Radius**: Distance from origin, must be non-negative
 * - **Azimuth**: Angle in radians, automatically normalized to [0, 2π) range
 * - **Origin**: Special point (0,0) handled separately if center action provided
 *
 * ## Input Validation
 * - Minimum 2 actions required for basic interpolation
 * - All radius values must be finite, positive, within JavaScript safe range
 * - All azimuth values must be finite, within JavaScript safe range
 * - No duplicate polar coordinates allowed
 * - At least 2 rays required (different azimuth values)
 * - All rays must have the same number of anchors for grid consistency
 *
 * ## Blending Algorithm
 * 1. Find the two adjacent rays that contain the target azimuth
 * 2. Calculate angular interpolation weights between these rays
 * 3. For each ray, find the two adjacent rings containing the target radius
 * 4. Calculate radial interpolation weights between these rings
 * 5. Apply bilinear interpolation to determine final animation weights
 * 6. Handle special cases for center action and edge boundaries
 *
 * @example Walk/Run Directional Movement
 * ```typescript
 * // Create actions for 4-directional movement at two speeds
 * const idle = mixer.clipAction(idleAnimationClip);
 *
 * // Walk actions (radius = 1)
 * const walkForward = mixer.clipAction(walkForwardAnimationClip);
 * const walkRight = mixer.clipAction(walkRightAnimationClip);
 * const walkBackward = mixer.clipAction(walkBackwardAnimationClip);
 * const walkLeft = mixer.clipAction(walkLeftAnimationClip);
 *
 * // Run actions (radius = 2)
 * const runForward = mixer.clipAction(runForwardAnimationClip);
 * const runRight = mixer.clipAction(runRightAnimationClip);
 * const runBackward = mixer.clipAction(runBackwardAnimationClip);
 * const runLeft = mixer.clipAction(runLeftAnimationClip);
 *
 * // Set up polar blend tree with 4-directional movement
 * const blendTree = new PolarBlendTree([
 *   // Walk speed (radius = 1)
 *   { action: walkForward, radius: 1, azimuth: MathUtils.degToRad(0) },    // Forward
 *   { action: walkLeft, radius: 1, azimuth: MathUtils.degToRad(90) },     // Left
 *   { action: walkBackward, radius: 1, azimuth: MathUtils.degToRad(180) }, // Backward
 *   { action: walkRight, radius: 1, azimuth: MathUtils.degToRad(270) },     // Right
 *
 *   // Run speed (radius = 2)
 *   { action: runForward, radius: 2, azimuth: MathUtils.degToRad(0) },     // Fast Forward
 *   { action: runLeft, radius: 2, azimuth: MathUtils.degToRad(90) },      // Fast Left
 *   { action: runBackward, radius: 2, azimuth: MathUtils.degToRad(180) },  // Fast Backward
 *   { action: runRight, radius: 2, azimuth: MathUtils.degToRad(270) },      // Fast Right
 * ], idle); // Center action for stationary state
 *
 * // Blend to medium speed northeast (45° at 1.5x speed)
 * blendTree.setBlend(1.5, MathUtils.degToRad(45));
 *
 * // Blend to slow walk forward
 * blendTree.setBlend(0.5, MathUtils.degToRad(0));
 * ```
 *
 * @public
 */
export declare class PolarBlendTree extends AnimationTree {
    private readonly tempAnchorMap;
    private readonly trackableAnchors;
    /** Optional center anchor at origin (0,0) for special blending behavior */
    private readonly centerAnchor?;
    /** Array of rays (constant azimuth lines) containing anchors, sorted by azimuth */
    private readonly rays;
    /** Array of rings (constant radius circles) containing anchors, sorted by radius */
    private readonly rings;
    /** Current radial position for blending calculations */
    private currentRadius;
    /** Current angular position for blending calculations, normalized to [0, 2π) */
    private currentAzimuth;
    /**
     * Creates a new polar blend tree with the specified animation actions.
     * Actions are organized into rays (by azimuth) and rings (by radius) for
     * efficient bilinear interpolation. Initializes all actions to stopped state
     * and validates clip durations.
     *
     * @param polarActions - Array of polar actions defining the blend space.
     *                      Must contain at least 2 actions with unique coordinates.
     * @param centerAction - Optional center action at origin (0,0)
     * @throws {Error} When fewer than 2 actions are provided
     * @throws {Error} When any action has non-finite radius or azimuth values
     * @throws {Error} When any action has non-positive radius
     * @throws {Error} When any action has values outside JavaScript's safe range
     * @throws {Error} When multiple actions have the same polar coordinates
     * @throws {Error} When fewer than 2 rays are created (insufficient azimuth variety)
     * @throws {Error} When rays don't have consistent anchor counts for valid grid
     * @throws {Error} When any animation clip duration is not a positive finite number
     * @see {@link assertValidNumber} for coordinate validation details
     * @see {@link assertValidPositiveNumber} for radius and duration validation details
     */
    constructor(polarActions: PolarAction[], centerAction?: AnimationAction);
    get blendValue(): {
        azimuth: number;
        radius: number;
    };
    /**
     * Sets the blend position in polar coordinates to determine animation weights.
     *
     * The azimuth is normalized to [0, 2π) range and radius must be non-negative.
     * When the position changes, animation weights are recalculated using bilinear
     * interpolation between the closest anchors.
     *
     * @param azimuth - Target angular position in radians (finite number). Will be normalized to [0, 2π).
     * @param radius - Target radial distance from origin (finite non-negative number).
     * @throws {Error} When azimuth is not a finite number
     * @throws {Error} When radius is not a finite non-negative number
     * @see {@link assertValidNumber} for azimuth validation details
     * @see {@link assertValidNonNegativeNumber} for radius validation details
     *
     * @example
     * ```typescript
     * // Blend to half speed, 45 degrees
     * blendTree.setBlend(0.5, MathUtils.degToRad(45));
     *
     * // Blend to full speed, straight back
     * blendTree.setBlend(1.0, MathUtils.degToRad(180));
     *
     * // Azimuth values are normalized to [0, 2π) range
     * blendTree.setBlend(1.0, MathUtils.degToRad(450)); // Becomes (1.0, ~1.57)
     * ```
     *
     * @public
     */
    setBlend(azimuth: number, radius: number): void;
    protected ["onEnterInternal"](): void;
    /**
     * Updates the global influence for all active anchors in the polar blend tree.
     *
     * Called when the tree's overall influence changes but relative weights between
     * anchors should remain the same. Applies the current tree influence to all
     * active anchors while maintaining their existing weight distribution from
     * the polar blending calculations.
     *
     * @override
     * @protected
     */
    protected updateAnchorsInfluence(): void;
    /**
     * Recalculates and updates animation weights based on current blend position.
     *
     * This is the core blending algorithm that:
     * 1. Finds the two adjacent rays containing the current azimuth
     * 2. Calculates angular interpolation weights between these rays
     * 3. Determines if blending occurs in the center region or outer grid
     * 4. Applies appropriate interpolation (linear for center, bilinear for grid)
     * 5. Updates active anchors set and applies calculated weights
     *
     * The method handles three distinct cases:
     * - **Center Region**: When radius < first ring radius, blends with center action
     * - **Grid Region**: When radius >= first ring radius, uses bilinear interpolation
     * - **Edge Cases**: Boundary conditions and wraparound azimuth handling
     *
     * @private
     */
    private updateAnchors;
    /**
     * Calculates bilinear interpolation weights for the four corner anchors in the polar grid.
     *
     * This method performs standard bilinear interpolation between four points arranged
     * in a rectangular grid pattern in polar space. The four corners are defined by:
     * - Inner ring vs outer ring (radial dimension)
     * - Left ray vs right ray (angular dimension)
     *
     * The bilinear interpolation formula combines the radial and angular interpolation
     * weights to determine how much each of the four corner anchors contributes to
     * the final blend result.
     *
     * @param weights - Map to store calculated weights for each anchor
     * @param lRayT - Weight for the left ray (0 = all left, 1 = all right)
     * @param rRayT - Weight for the right ray (0 = all left, 1 = all right)
     * @param lRayIndex - Index of the left ray in the rays array
     * @param rRayIndex - Index of the right ray in the rays array
     *
     * @throws {Error} When no ring pair contains the current radius (should never happen)
     *
     * @private
     */
    private calculateBilinearWeights;
}
