import { type CellComplex, MatN, Rotor4, type Tetrahedralization, VecN } from '@holotope/core'; export interface ConvexBoundary4 { /** Packed R4 positions. */ readonly positions: Float64Array; /** Four indices per boundary tetrahedron. */ readonly indices: Uint32Array; /** Optional count excluding derived centroid/helper vertices. */ readonly sourceVertexCount?: number; } export interface MassProperties4Options { /** Uniform density. Default 1. */ density?: number; /** Override the vertices used to choose the numerical reference point. */ sourceVertexCount?: number; /** Relative convergence threshold for the symmetric Jacobi solve. */ jacobiTolerance?: number; } export interface MassProperties4 { readonly volume: number; readonly mass: number; /** Center of mass in the source coordinate frame. */ readonly centerOfMass: VecN; /** Integral of (x-COM)(x-COM)ᵀ dm in the source coordinate frame. */ readonly covarianceAtCenter: MatN; /** Columns map principal-frame vectors into the source coordinate frame. */ readonly principalAxes: MatN; /** The same principal→source frame on the Spin(4) fast path. */ readonly principalRotor: Rotor4; /** Diagonal of Qᵀ C Q, ordered ascending. */ readonly principalSecondMoments: Float64Array; /** Six diagonal inertias in planes 01,02,03,12,13,23. */ readonly inertiaDiagonal: Float64Array; } /** * Integrates uniform 4-volume and second moments from a tetrahedralized * convex boundary. Each boundary tetrahedron is coned to an interior * numerical reference point, producing one 4-simplex. * * Convexity is part of this contract: absolute cone volumes are used, so a * non-convex or self-intersecting boundary must first provide a consistently * oriented signed-volume decomposition through a future, separate API. */ export declare function massPropertiesFromConvexBoundary4(boundary: ConvexBoundary4, options?: MassProperties4Options): MassProperties4; /** * Changes packed source-frame points into the centered principal frame. * Applying `properties.principalRotor` and then adding the center of mass * reconstructs the original points. */ export declare function rebasePositionsToPrincipalFrame4(positions: ArrayLike, properties: MassProperties4): Float64Array; export declare function massPropertiesFromTetrahedralization4(tetrahedralization: Tetrahedralization, options?: MassProperties4Options): MassProperties4; /** * Uses all simplex 3-cell groups as a tetrahedralized convex boundary. * * @example * An orthotope's mass properties are closed-form, which makes it a good way to * read what each field means. With edge lengths `a` and density `ρ`, the * volume is `∏aᵢ`, the principal second moments are `m aᵢ²/12`, and the six * plane inertias are their pair sums `m(aᵢ² + aⱼ²)/12`: * ```ts * const body = tetrahedralizeCuboidCells( * createHyperrectangle({ dim: 4, edgeLengths: [2, 3, 5, 7], maxCellDimension: 3 }) * ); * // MassProperties4. * const properties = massPropertiesFromCellComplex4(body); * * log(properties.volume); // 210 * // One per principal axis, ordered by the eigensolver. * log(Array.from(properties.principalSecondMoments).length); // 4 * // One per plane, in bivector order 01, 02, 03, 12, 13, 23. * log(Array.from(properties.inertiaDiagonal).length); // 6 * ``` */ export declare function massPropertiesFromCellComplex4(complex: CellComplex, options?: MassProperties4Options): MassProperties4; /** * Exact mass properties of a uniform solid R4 hyperbox about its own centre. * * The box is the axis-aligned region `|xᵢ| ≤ halfExtents[i]`, so its centre of * mass is the origin of the frame the half-extents are written in. Volume is * `16 h₀h₁h₂h₃` and the source-frame covariance is diagonal with entries * `m hᵢ² / 3`, from which the six plane inertias `m (hᵢ² + hⱼ²) / 3` follow. * * **Frame.** Half-extents are read in the caller's authored axes; the result is * the canonical principal representation, exactly as * {@link massPropertiesFromConvexBoundary4} returns for the same solid. Because * `principalSecondMoments` is ordered ascending and a box's second moment grows * with its extent, the principal frame is the authored axes **permuted so the * half-extents ascend**. For extents that already ascend the permutation is the * identity and `principalRotor` is the identity rotor. * * That matters when pairing this with a collider. `RigidBody4.fromMassProperties` * adopts `principalRotor` as the body's rotation, so a `HyperboxCollider4` * sharing that body must be given its half-extents **in the same principal * order** — sorted ascending — or the collision shape and the mass distribution * will describe two differently oriented boxes. This is the analytic * counterpart of rebasing a complex with `rebasePositionsToPrincipalFrame4`. * * **Uniform solid only.** This describes a box of homogeneous material. A * collider is frequently a proxy for something whose mass is distributed * otherwise — a hull around a dense core, a shell, an avatar whose handling is * authored rather than physical — and for those the authored inertia is the * right answer and this function is not. */ export declare function massPropertiesOfHyperbox4(halfExtents: ArrayLike, options?: MassProperties4Options): MassProperties4; /** * Exact mass properties of a uniform solid R4 glome about its own centre. * * Volume is `π² r⁴ / 2`. The covariance is isotropic: integrating `|x|²` over * the ball gives `∫₀ʳ 2π² s⁵ ds = π² r⁶ / 3`, so `∫|x|² dm = m · 2r² / 3` and, * by symmetry, each `∫xᵢ² dm = m r² / 6`. Every plane inertia is therefore * `m r² / 3` — the same value in all six planes. * * **Frame.** A ball has no preferred axes, so the covariance is a multiple of * the identity, the principal frame is the identity frame, and `principalRotor` * is the identity rotor. Pairing this with a `GlomeCollider4` needs no * reorientation. * * **Uniform solid only**, on the same terms as * {@link massPropertiesOfHyperbox4}. */ export declare function massPropertiesOfGlome4(radius: number, options?: MassProperties4Options): MassProperties4; //# sourceMappingURL=mass-properties4.d.ts.map