import { Box, Polygon } from '@expofp/geometry';
import { type RegularBooth } from '../../../../store/BoothStore.js';
/** What a badge's anchor search reads off its booth. */
export type BadgeBooth = Pick<RegularBooth, 'rect' | 'rotate'>;
/** What a booth's badge must fit in. */
export interface BadgeFootprint {
    /** The body's shape, built once for the outline and the badge's anchor search alike. */
    readonly geometry: BadgeGeometry;
    /** How far the outline reaches into the body; 0 without one. */
    readonly outlineInset: number;
}
/** A footprint's shape, as the anchor search reads it. */
export interface BadgeGeometry {
    /** The booth's body (its first path) as triangles; empty without paths. */
    readonly triangles: number[][][];
    readonly polygon: Polygon;
    /** The footprint's outer edge. */
    readonly edges: FootprintEdge[];
    readonly bbox: Box | null;
}
/**
 * The badge's footprint: the booth's first path. Later paths are usually an outline drawn as a band
 * over the body's edge, so their reach into the body comes along for the badge to keep clear of. A
 * path that does not reach the edge is an inner element, not an outline, and is left out.
 * @param booth - The booth.
 * @returns The body and the outline's reach into it.
 */
export declare function getBoothBadgeFootprint(booth: Pick<RegularBooth, 'paths' | 'layer'>): BadgeFootprint;
/** Where a badge sits in one booth corner, and how large it may grow there. */
export interface BadgeFit {
    /** The x of the badge's top-left corner on the plan, before rotation. */
    readonly x: number;
    /** The y of the badge's top-left corner on the plan, before rotation. */
    readonly y: number;
    /** The largest scale that keeps the badge inside the booth's footprint. */
    readonly maxScale: number;
}
/**
 * The places a booth's badge can sit, one per booth corner, each computed on the first visit to
 * that corner and kept.
 *
 * The plan's roll moves the badge to another booth corner every quarter turn, and every badge on
 * the plan moves in the same frame. Finding a corner's anchor tests the booth's vertices against
 * its own triangles, so it is too slow to repeat for hundreds of badges at once. The result
 * depends only on the corner: the rotation the scale search uses is the booth's own plus the
 * quarter turns to that corner, the same at every visit to it up to whole turns of 2π.
 *
 * The first visit to a corner still searches, for every badge at once, so {@link prefetch} works
 * the other corners out ahead, while the page is idle.
 */
export declare class BoothBadgeAnchors {
    private readonly booth;
    private readonly border;
    private readonly source;
    /** The badges with corners still to work out while the page is idle, in the order queued. */
    private static readonly idle;
    private static idleScheduled;
    private readonly fits;
    /** The rotation at corner 0 the idle work counts quarter turns from. */
    private prefetchRotation;
    private readonly triangles;
    private readonly polygon;
    /** The footprint's outer edge. */
    private readonly edges;
    private readonly bbox;
    /** The booth's distinct vertices in first-seen order, built on the first search. */
    private vertices;
    /**
     * @param booth - The booth the badge belongs to.
     * @param geometry - The booth's footprint, from {@link buildBadgeGeometry}.
     * @param border - How far the badge stays in from the booth's edge.
     * @param source - The badge's width and height at scale 1.
     */
    constructor(booth: BadgeBooth, geometry: BadgeGeometry, border: number, source: {
        readonly x: number;
        readonly y: number;
    });
    /**
     * The badge's place in a booth corner.
     * @param corner - The booth corner, clockwise from top-left (0) to bottom-left (3).
     * @param rotation - The badge's rotation in radians: the booth's own plus the quarter turns that
     *   brought the badge to this corner. Read on the first visit only.
     * @returns The anchor and the largest scale, the same object at every visit.
     */
    fit(corner: number, rotation: number): BadgeFit;
    /**
     * Works out the three corners not yet visited while the page is idle, so the first quarter turn
     * into each finds it ready. Queuing again while queued changes nothing.
     * @param rotation - The badge's rotation at corner 0: the booth's own.
     */
    prefetch(rotation: number): void;
    /** Drops the idle work {@link prefetch} queued and has not done yet. */
    cancelPrefetch(): void;
    private static scheduleIdle;
    /** Runs the idle work for one {@link FRAME_SLICE_MS} slice, where no idle period is on offer. */
    private static runSlice;
    /**
     * Works out one corner after another while the idle period lasts, for at most a slice, then asks
     * for another.
     * @param deadline - How much of the idle period is left.
     */
    private static runIdle;
    /**
     * Works out the next corner not yet known, at the rotation the quarter turns to it give.
     * @returns Whether a corner is still unknown after this one.
     */
    private prefetchNext;
    /**
     * Searches a corner: the anchor, the largest scale at it, then the move off slanted sides.
     * @param corner - The booth corner, clockwise from top-left (0).
     * @param rotation - The badge's rotation at that corner, in radians.
     * @returns The corner's fit.
     */
    private compute;
    /**
     * Moves the anchor along the badge's axes where a slanted booth side comes nearer than the border
     * to the badge's left or top side.
     * @param anchor - The badge's anchor.
     * @param scale - The badge's largest scale.
     * @param rotation - The badge's rotation, in radians.
     * @returns The moved anchor; `null` when no move is needed or it would leave the booth.
     */
    private nudge;
    /**
     * The largest scale the booth's rect allows. At odd corners the badge's width and height lie
     * along the booth's height and width.
     * @param swapped - Whether the badge's axes are swapped against the booth's.
     * @returns The scale.
     */
    private rectMaxScale;
    /**
     * The booth vertex, moved in by the border, nearest the target corner of the booth's bounding
     * box and still inside the booth. Uses booth.rotate (the booth's true tilt) for the fallback,
     * never the badge's stepped rotation: the booth does not move when the badge steps.
     *
     * The candidates are tested nearest first, so the search stops at the first one inside instead
     * of testing every vertex. Ties keep the vertex seen first, as a full scan would.
     * @param signX - 1 to aim at the left edge, -1 at the right.
     * @param signY - 1 to aim at the top edge, -1 at the bottom.
     * @returns The anchor.
     */
    private findAnchor;
    /**
     * Binary-searches the largest scale, up to the rect's cap, that keeps all badge corners inside
     * the booth's footprint.
     * @param anchorX - The badge's anchor.
     * @param anchorY - The badge's anchor.
     * @param rectMaxScale - The cap the booth's rect allows.
     * @param rotation - The badge's rotation, in radians.
     * @returns The scale; the cap itself when the booth has no footprint or the anchor lies outside.
     */
    private clampScale;
    /**
     * Whether the badge's three corners away from the anchor lie inside the booth's footprint.
     * @param anchorX - The badge's anchor.
     * @param anchorY - The badge's anchor.
     * @param scale - The badge's scale.
     * @param rotation - The badge's rotation, in radians.
     * @returns Whether they do.
     */
    private fitsAt;
    /**
     * The booth's distinct vertices, in the order the triangles first name them.
     * @returns The vertices, built once.
     */
    private distinctVertices;
}
/**
 * The bounding box of a booth's triangles.
 * @param triangles - The triangles, as `[x, y]` vertex triples.
 * @returns The box, or `null` when there are no triangles.
 */
export declare function trianglesBoundingBox(triangles: number[][][]): Box | null;
/** A segment of a footprint's outer edge. */
export type FootprintEdge = [number[], number[]];
/**
 * The shape the anchor search reads off a footprint's triangles.
 * @param triangles - The triangles.
 * @returns The triangles with their polygon, outer edge and bounding box.
 */
export declare function buildBadgeGeometry(triangles: number[][][]): BadgeGeometry;
//# sourceMappingURL=booth-badge-anchor.d.ts.map