@ue-too/board
Version:
<h1 align="center"> uē-tôo </h1> <p align="center"> pan, zoom, rotate, and more with your html canvas. </p>
195 lines (194 loc) • 6.8 kB
TypeScript
/**
* Constraints for camera rotation defining an angular range with direction.
*
* @property start - Starting angle of the allowed range in radians
* @property end - Ending angle of the allowed range in radians
* @property ccw - If true, the range is measured counter-clockwise from start to end. If false, clockwise
* @property startAsTieBreaker - When clamping and distance to start equals distance to end, clamp to start if true, end if false
*
* @remarks
* Rotation limits define an angular arc. The direction (ccw) determines which
* way around the circle the range extends from start to end.
*
* For example:
* - start=0, end=π/2, ccw=true: allows 0 to π/2 (0° to 90°)
* - start=0, end=π/2, ccw=false: allows 0 to -3π/2 going clockwise (0° to 270° the other way)
*
* @category Camera
*/
export type RotationLimits = {
start: number;
end: number;
ccw: boolean;
startAsTieBreaker: boolean;
};
/**
* Experimental rotation boundary type with positive/negative direction semantics.
*
* @property start - Starting angle of the boundary in radians
* @property end - Ending angle of the boundary in radians
* @property positiveDirection - If true, range extends in positive angle direction. If false, negative direction
* @property startAsTieBreaker - When equidistant from start and end, prefer start if true, end if false
*
* @remarks
* This is an experimental alternative to {@link RotationLimits} with different direction semantics.
*
* @category Camera
*/
export type RotationBoundary = {
start: number;
end: number;
positiveDirection: boolean;
startAsTieBreaker: boolean;
};
/**
* Clamps a rotation angle to stay within specified angular limits.
*
* @param rotation - The rotation angle to clamp in radians
* @param rotationLimits - Optional rotation constraints with direction
* @returns The clamped rotation angle, or original if already within limits
*
* @remarks
* If the rotation is outside the allowed arc, it's clamped to the nearest
* boundary (start or end). When equidistant from both, the `startAsTieBreaker`
* flag determines which boundary to use.
*
* The rotation is normalized to [0, 2π] before clamping.
*
* @example
* ```typescript
* const limits = { start: 0, end: Math.PI/2, ccw: true, startAsTieBreaker: true };
*
* clampRotation(Math.PI/4, limits); // π/4 (within range)
* clampRotation(Math.PI, limits); // π/2 (clamped to end)
* clampRotation(-0.1, limits); // 0 (clamped to start)
* ```
*
* @category Camera
*/
export declare function clampRotation(rotation: number, rotationLimits?: RotationLimits): number;
/**
* Checks if a rotation angle is within specified angular limits.
*
* @param rotation - The rotation angle to check in radians
* @param rotationLimits - Optional rotation constraints with direction
* @returns True if rotation is within the allowed arc or no limits specified, false otherwise
*
* @remarks
* Returns true if:
* - No limits are specified (undefined)
* - Start and end angles are effectively equal (full circle allowed)
* - Rotation falls within the arc from start to end in the specified direction
*
* The rotation is normalized to [0, 2π] before checking.
*
* @example
* ```typescript
* const limits = { start: 0, end: Math.PI/2, ccw: true, startAsTieBreaker: true };
*
* rotationWithinLimits(Math.PI/4, limits); // true (within range)
* rotationWithinLimits(Math.PI, limits); // false (outside range)
* rotationWithinLimits(0, limits); // true (at start)
* rotationWithinLimits(Math.PI/2, limits); // true (at end)
* ```
*
* @category Camera
*/
export declare function rotationWithinLimits(rotation: number, rotationLimits?: RotationLimits): boolean;
/**
* Checks if a rotation angle is within an experimental rotation boundary.
*
* @param rotation - The rotation angle to check in radians
* @param rotationBoundary - Rotation boundary with positive/negative direction
* @returns True if rotation is within the boundary range, false otherwise
*
* @remarks
* This is an experimental alternative to {@link rotationWithinLimits} using
* positive/negative direction semantics instead of ccw/cw.
*
* @category Camera
*/
export declare function rotationWithinBoundary(rotation: number, rotationBoundary: RotationBoundary): boolean;
/**
* Normalizes an angle to the range [0, 2π).
*
* @param angle - Angle in radians (can be any value)
* @returns Equivalent angle in the range [0, 2π)
*
* @remarks
* This function wraps angles to the standard [0, 2π) range. Useful for
* ensuring consistent angle representation when comparing or storing angles.
*
* @example
* ```typescript
* normalizeAngleZero2TwoPI(0); // 0
* normalizeAngleZero2TwoPI(Math.PI); // π
* normalizeAngleZero2TwoPI(3 * Math.PI); // π (wraps around)
* normalizeAngleZero2TwoPI(-Math.PI/2); // 3π/2 (negative becomes positive)
* normalizeAngleZero2TwoPI(2 * Math.PI); // 0 (full rotation)
* ```
*
* @category Camera
*/
export declare function normalizeAngleZero2TwoPI(angle: number): number;
/**
* Calculates the signed angular distance between two angles, taking the shorter path.
*
* @param from - Starting angle in radians
* @param to - Target angle in radians
* @returns Signed angular difference in radians, in the range (-π, π]
*
* @remarks
* Returns the shortest angular path from `from` to `to`:
* - Positive value: rotate counter-clockwise (positive direction)
* - Negative value: rotate clockwise (negative direction)
* - Always returns the smaller of the two possible paths
*
* @example
* ```typescript
* angleSpan(0, Math.PI/2); // π/2 (90° ccw)
* angleSpan(Math.PI/2, 0); // -π/2 (90° cw)
* angleSpan(0, 3*Math.PI/2); // -π/2 (shorter to go cw)
* angleSpan(3*Math.PI/2, 0); // π/2 (shorter to go ccw)
* angleSpan(0, Math.PI); // π (180°, ambiguous)
* ```
*
* @category Camera
*/
export declare function angleSpan(from: number, to: number): number;
/**
* Converts degrees to radians.
*
* @param deg - Angle in degrees
* @returns Equivalent angle in radians
*
* @example
* ```typescript
* deg2rad(0); // 0
* deg2rad(90); // π/2
* deg2rad(180); // π
* deg2rad(360); // 2π
* deg2rad(-45); // -π/4
* ```
*
* @category Camera
*/
export declare function deg2rad(deg: number): number;
/**
* Converts radians to degrees.
*
* @param rad - Angle in radians
* @returns Equivalent angle in degrees
*
* @example
* ```typescript
* rad2deg(0); // 0
* rad2deg(Math.PI/2); // 90
* rad2deg(Math.PI); // 180
* rad2deg(2 * Math.PI); // 360
* rad2deg(-Math.PI/4); // -45
* ```
*
* @category Camera
*/
export declare function rad2deg(rad: number): number;