import { BufferGeometry, Mesh, type Material } from 'three'; import { type CellComplex, type HyperplaneSlice4, type Projection, type RepresentationCellChartN, type SourceCellReferenceN, type TransformN } from '@holotope/core'; export interface SlicedComplex3DOptions { material?: Material; /** * When set, the section is rendered **through this projection** — the * same 3D space as `ProjectedEdges3D` output — instead of the slice's * own display frame. Use it to overlay the cut inside a projected * wireframe of the same object. */ projection?: Projection; /** * Construction-time palette: one hex color is requested for each source * tetrahedron and cached. Remarching reuses that palette; it does not call * this function again. Use `recolorBySourceTet()` when selection or other * application state changes. Map tets to the polytope's own cells (e.g. * `Math.floor(tet / tetsPerCell)`) to paint the section as an assembly of * cells. Requires a material with `vertexColors: true` to be visible. */ colorForTet?: (tetIndex: number) => number; } /** Exact construction record for one emitted section vertex. */ export interface SliceCrossingProvenanceN { readonly edgeVertices: readonly [number, number]; /** `point = from + parameter * (to - from)` in current ambient R4 state. */ readonly parameter: number; } /** * Render product: the exact cross-section of a 4D cell complex with a * hyperplane, rendered as a three.js Mesh. * * The complex must carry tetrahedral 3-cells (run `tetrahedralizeCuboidCells` * on cuboid-celled complexes first). Each update transforms the vertices in * 4D (Float64 CPU golden path), runs marching tetrahedra against the * hyperplane, and uploads the resulting triangle soup expressed in the * slice's own display frame. * * That default frame is intentionally **not** the coordinate system of a * projected wireframe. To overlay a section on `ProjectedEdges3D` or * `ProjectedSurface3D`, pass that product's same projection through * `options.projection`; otherwise the two honest representations occupy * different local frames and should be displayed as separate views. * * Triangle winding is not globally consistent, so the default material is * double-sided; flat normals are recomputed per update. */ export declare class SlicedComplex3D { readonly complex: CellComplex; readonly slice: HyperplaneSlice4; readonly geometry: BufferGeometry; readonly object: Mesh; private readonly tets; private readonly tetReferences; private readonly worldPositions; private readonly positionAttribute; /** Optional second reduction applied after the exact ambient R4 section. */ readonly projection: Projection | undefined; private readonly ambientSection; private readonly provenance; private readonly crossingProvenance; private readonly colorAttribute; private readonly tetColors; private sourceTransform; /** * Builds the section product and allocates for the largest section the * tetrahedra can produce, so a moving cut never reallocates. * * @param complex - Source complex in R⁴, carrying tetrahedral 3-cells. * Marching proceeds over tetrahedra, so a cuboid-celled complex must be * decomposed with `tetrahedralizeCuboidCells` first. * @param slice - The cutting hyperplane. It is retained rather than copied, * so changing its `offset` or normal moves the cut on the next update. * @param options - `material` overrides the appearance; `projection` * expresses the section in a projection's frame instead of the slice's own, * which is what allows a cut to be drawn inside the wireframe it came from. * * @example * A section that sweeps as the offset moves. It is empty once the * hyperplane passes beyond the object's extent. * ```ts * const solid = tetrahedralizeCuboidCells( * createHypercube({ dim: 4, maxCellDimension: 3 }) * ); * const slice = HyperplaneSlice4.axisAligned(3, 0); * const section = new SlicedComplex3D(solid, slice); * scene.add(section.object); * * slice.offset = 0.25; * section.update(new TransformN(4)); * section.triangleCount; // reflects this cut, not the source * ``` */ constructor(complex: CellComplex, slice: HyperplaneSlice4, options?: SlicedComplex3DOptions); /** * Recomputes the cross-section. Call whenever the 4D transform, the slice * offset/normal, or the source positions change. * * @param transform - Optional R4 source transform. A transform of another * dimension is rejected before the section geometry is remarched. */ update(transform?: TransformN): void; /** * Rebuild the cached source-tetrahedron palette and recolor the current * section without remarching its geometry. * * The product must have been constructed with `colorForTet`, which opts it * into a vertex-color buffer. The callback is evaluated exactly once per * source tetrahedron; invalid colors are rejected before the existing * palette is changed. */ recolorBySourceTet(colorForTet: (tetIndex: number) => number): void; /** Write cached source-tet colors onto the current triangle soup. */ private applyActiveColors; /** Per-face normals over the active draw range only. */ private computeFlatNormals; /** Number of triangles in the current section. */ get triangleCount(): number; /** * Provenance lookup for picking: the source tetrahedron of a rendered * triangle. `faceIndex` is what `Raycaster` reports when intersecting * `object`; the returned index counts into this complex's concatenated * tetrahedral cells. */ sourceTetOfFace(faceIndex: number): number; /** * Current rendered face indices produced by one source tetrahedron. * * The result reflects the latest `update()` and is empty when that * tetrahedron does not intersect the current slice. This is the inverse of * `sourceTetOfFace()` for the current remarch, not a general visibility * abstraction shared with projections. */ facesOfSourceTet(tetIndex: number): number[]; /** The four source-complex vertex indices of a tetrahedron by index. */ sourceTetVertices(tetIndex: number): [number, number, number, number]; /** Lifecycle-aware reference to one concatenated source tetrahedron. */ sourceReferenceOfTet(tetIndex: number): SourceCellReferenceN; /** Lifecycle-aware reference to the source tetrahedron of a rendered face. */ sourceReferenceOfFace(faceIndex: number): SourceCellReferenceN; /** * Renderer-independent chart record used to resolve visible points back to * retained source cells. A projected section preserves the triangle-to-cell * record but honestly marks its point lift unavailable. */ sourceCellChart(): RepresentationCellChartN; /** Source edge and exact interpolation parameter of one rendered corner. */ sourceCrossingOfFaceVertex(faceIndex: number, corner: number): SliceCrossingProvenanceN; /** Exact construction records for the three corners of one rendered face. */ sourceCrossingsOfFace(faceIndex: number): readonly [SliceCrossingProvenanceN, SliceCrossingProvenanceN, SliceCrossingProvenanceN]; dispose(): void; } //# sourceMappingURL=sliced-complex.d.ts.map