/** * cropGeometry — pure coordinate + quad helpers behind the item-7 * draggable-corner crop editor (`RectCropPreview`). * * The editor shows the full result image with a `resizeMode="contain"` * letterbox: the image is centred and uniformly scaled to fit the layout * box, leaving symmetric bars on one axis. The 4 draggable corners live in * ON-SCREEN coordinates (the touch space PanResponder reports), but the * native crop needs IMAGE-PIXEL coordinates. These helpers are the * letterbox transform and its inverse — extracted verbatim from * `example/InscribedRectDebug.tsx` (~lines 178-204), which mapped an * inscribed-rect from image px → screen the same way. * * Everything here is pure (no React, no native) so it's unit-testable * without booting a render — same posture as `contentRotationDeg` and * `buildPanoramaInitialSettings`. * * Coordinate conventions: * - A `Point` is `{ x, y }`. Screen points are in the layout box's * local space (origin = box top-left); image points are in pixel * space (origin = image top-left, range [0..imageW] × [0..imageH]). * - A `Quad` is exactly 4 points. `orderQuadCorners` canonicalises * winding to [TL, TR, BR, BL] so downstream native perspective * rectify gets corners in the order it expects. */ /** A 2-D point in either screen-local or image-pixel space. */ export interface Point { x: number; y: number; } /** The contain-fit letterbox layout of the image inside its box. */ export interface ContainLayout { /** Layout box width (on-screen px). */ width: number; /** Layout box height (on-screen px). */ height: number; } /** Exactly four points (corners of a crop quad). */ export type Quad = [Point, Point, Point, Point]; /** * The contain-fit transform: uniform scale + centring offsets that map * image-pixel space into the on-screen layout box. Returns `null` when * any dimension is non-positive (nothing to lay out). * * `scale` is `min(box.w / imageW, box.h / imageH)` — the same * `resizeMode="contain"` math RN's applies — and `offX`/`offY` * centre the scaled image, producing the letterbox bars. */ export declare function containFit(layout: ContainLayout, imageW: number, imageH: number): { scale: number; offX: number; offY: number; } | null; /** * Map an on-screen point (layout-box local coords) → image-pixel coords. * Inverse of {@link imageToScreen}. The result is clamped to * `[0..imageW] × [0..imageH]` so a corner dragged onto / past the * letterbox bar still yields a valid in-bounds pixel for the native crop * (the user can't pick pixels that don't exist). * * Returns the un-mapped point unchanged when the layout is degenerate * (see {@link containFit}) — the caller has no valid letterbox yet. */ export declare function screenToImage(point: Point, layout: ContainLayout, imageW: number, imageH: number): Point; /** * Map an image-pixel point → on-screen point (layout-box local coords). * Inverse of {@link screenToImage}. Used to seed the draggable corners * from an image-space initial rect and to keep the overlay aligned to the * letterboxed image. * * Returns the un-mapped point unchanged when the layout is degenerate. */ export declare function imageToScreen(point: Point, layout: ContainLayout, imageW: number, imageH: number): Point; /** * Re-order 4 arbitrary corner points into canonical * [TL, TR, BR, BL] (clockwise from top-left) winding. * * Strategy (robust to slight perspective skew, no trig): * - Top two = the two points with the smallest `y`; bottom two = the * largest `y`. Within each pair, the smaller `x` is left. * Ties on `y` (a perfectly axis-aligned rect) resolve deterministically * because the sort is stable and we then split by `x`. * * This matches the corner order the native `cropToQuad` perspective * rectify expects (dst rect: TL→TR→BR→BL). */ export declare function orderQuadCorners(pts: Quad): Quad; /** * 2× the signed area of a polygon via the shoelace formula. Positive for * counter-clockwise winding, negative for clockwise, ~0 for degenerate. * Exported for tests + reused by {@link isQuadValid}. */ export declare function signedArea2(pts: Quad): number; /** * True when the 4 points form a usable crop quad: * 1. **Non-degenerate area** — `|signed area|` ≥ `minArea` (default * `1`, i.e. at least 1 px²). Rejects all-collinear / zero-size. * 2. **Convex** — every cross-product of consecutive edges shares one * sign (allowing zero for a straight, axis-aligned corner). Rejects * self-intersecting / "bowtie" quads, which the native perspective * warp can't rectify. * * Operates on the points in their given winding (call `orderQuadCorners` * first if you need canonical order); convexity is winding-agnostic. */ export declare function isQuadValid(pts: Quad, minArea?: number): boolean; /** * Target rectangle size for the perspective `dst` quad, derived from the * 4 ORDERED ([TL, TR, BR, BL]) image-pixel corners: * - `w` = average of the top edge (TL→TR) and bottom edge (BL→BR) * lengths. * - `h` = average of the left edge (TL→BL) and right edge (TR→BR) * lengths. * Averaging opposite edges gives a stable output size for a skewed quad * (each pair of opposite edges differs under perspective; the mean is the * least-distorting target). Rounds to whole pixels — the native crop * allocates an integer-sized bitmap. * * Caller must pass corners already in [TL, TR, BR, BL] order (use * {@link orderQuadCorners}); the math assumes that winding. */ export declare function rectSizeForQuad(orderedImagePts: Quad): { w: number; h: number; }; /** * True when an ORDERED ([TL, TR, BR, BL]) image-pixel quad is, within * `tolerancePx`, an axis-aligned rectangle — i.e. the cheap axis-aligned * `cropToRect` path applies and no perspective warp is needed. The parent * uses this to choose `cropToRect` vs `cropToQuad`. * * Checks the two top/bottom corners share a `y` and the two left/right * corners share an `x`, all within tolerance. */ export declare function isAxisAlignedRect(orderedImagePts: Quad, tolerancePx?: number): boolean; //# sourceMappingURL=cropGeometry.d.ts.map