import { VecN } from '@holotope/core'; import { type ContactPatchKind4, type ContactPlaneIntersectionDiagnostics4 } from './contact-polyhedron4.js'; import { type EpaOptions4, type EpaPenetrationResult4 } from './epa4.js'; import { type SupportFeatureId, type SupportShapeN } from './support-shape.js'; export interface PolytopeContactOptions4 { readonly epaOptions?: EpaOptions4; /** Supporting-facet classification band. Default 1e-10. */ readonly facetTolerance?: number; /** Halfspace feasibility band in world units. Default 1e-9. */ readonly clipTolerance?: number; /** Point merge and boundary-feature band. Default 1e-8. */ readonly vertexTolerance?: number; /** Affine-rank band. Default 1e-10. */ readonly rankTolerance?: number; /** Maximum retained solver points. Default 8; must be in [4, 32]. */ readonly maxSolverPoints?: number; /** Maximum four-vertex facet candidates per shape. Default 250000. */ readonly maxFacetCandidates?: number; } export type PolytopeContactStatus4 = 'unsupported' | 'separated' | 'touching' | 'penetrating' | 'indeterminate'; export type PolytopeContactReason4 = 'complete' | 'shape-a-not-vertex-enumerable' | 'shape-b-not-vertex-enumerable' | 'epa-separated' | 'epa-indeterminate' | 'facet-candidate-limit' | 'degenerate-polytope' | 'facet-enumeration-failed' | 'compiled-topology-invalid' | 'contact-intersection-failed'; /** Stable minimal boundary face expressed in source vertex identities. */ export interface PolytopeBoundaryFeature4 { readonly key: string; readonly vertexFeatureIds: readonly SupportFeatureId[]; readonly dimension: 0 | 1 | 2 | 3; } export interface PolytopeContactVertex4 { /** Persistent identity derived from the two minimal source faces. */ readonly id: string; /** World-space point after translating A into just-touching alignment. */ readonly point: VecN; readonly featureA: PolytopeBoundaryFeature4; readonly featureB: PolytopeBoundaryFeature4; } export interface PolytopeFacet4 { /** Outward world-space facet normal for the halfspace normal ยท point <= offset. */ readonly normal: VecN; readonly offset: number; readonly key: string; readonly vertexFeatureIds: readonly SupportFeatureId[]; readonly conditionEstimate: number; } /** * Where one polytope's facet description came from and what it cost. * * `topologySource` is the field that matters for performance: `compiled` * means the facets were already known and this query only had to pick * supporting ones, while `enumerated` means they were recovered here, and * `queryFacetCandidates` is what that cost. A shape re-enumerating on every * query should be compiled once instead. */ export interface PolytopeHullDiagnostics4 { /** Vertices the hull was built from. */ readonly sourceVertices: number; /** Candidate count paid during original compilation. */ readonly facetCandidates: number; /** Candidates that turned out to support the hull. */ readonly supportingCandidates: number; /** Facets in the final description. */ readonly facets: number; /** Whether the topology was reused from compilation or recovered here. */ readonly topologySource: 'compiled' | 'enumerated'; /** Candidate hyperplanes evaluated by this contact query. */ readonly queryFacetCandidates: number; } /** * Everything a polytope contact query is willing to say about its own cost * and confidence: the halfspace-intersection funnel it inherits, what each * hull description cost, and how far EPA got. * * `epaErrorBound` is the one to read before trusting a depth. EPA brackets the * penetration between an inner-polytope lower bound and a support-plane upper * bound, and this is the width of that bracket: the true depth lies within it * of the reported one. A width comparable to the depth means the expansion was * cut short and the depth is an estimate rather than a measurement. * * `null` means EPA established no bracket at all. It is intentionally distinct * from zero, which is the strongest possible statement: a zero-width bracket. */ export interface PolytopeContactPatchDiagnostics4 extends ContactPlaneIntersectionDiagnostics4 { /** Hull description cost for the first polytope. */ readonly hullA: PolytopeHullDiagnostics4; /** The same for the second. */ readonly hullB: PolytopeHullDiagnostics4; /** Support queries EPA made while expanding. */ readonly epaSupports: number; /** Facets in its final polytope. */ readonly epaFacets: number; /** Expansion steps taken. */ readonly epaExpansions: number; /** Width of EPA's penetration-depth bracket, or `null` when none exists. */ readonly epaErrorBound: number | null; } export interface PolytopeContactPatch4 { readonly kind: ContactPatchKind4; readonly intrinsicDim: 0 | 1 | 2 | 3; /** Minimum-translation direction from ordered B toward ordered A. */ readonly normal: VecN; readonly planeOffset: number; /** Conservative directional separation required to align the support faces. */ readonly penetrationDepth: number; readonly alignmentShift: number; readonly translationA: VecN; readonly vertices: readonly PolytopeContactVertex4[]; readonly solverPoints: readonly PolytopeContactVertex4[]; readonly diagnostics: PolytopeContactPatchDiagnostics4; } export interface PolytopeContactResult4 { readonly status: PolytopeContactStatus4; readonly reason: PolytopeContactReason4; readonly epa: EpaPenetrationResult4 | null; readonly patch: PolytopeContactPatch4 | null; } /** * EPA-seeded complete contact patch for vertex-enumerable convex R4 polytopes. * Facets are derived from source vertex IDs, then both resolved hulls are * intersected with the common contact hyperplane. */ export declare function polytopeContactPatch4(shapeA: SupportShapeN, shapeB: SupportShapeN, options?: PolytopeContactOptions4): PolytopeContactResult4; /** Canonical persistent identity for a pair of minimal polytope faces. */ export declare function polytopeContactVertexId4(featureA: PolytopeBoundaryFeature4, featureB: PolytopeBoundaryFeature4): string; //# sourceMappingURL=polytope-contact4.d.ts.map