/** @packageDocumentation
 * @module Polyface
 */
import { GeometryQuery } from "../curve/GeometryQuery";
import { GeometryHandler } from "../geometry3d/GeometryHandler";
import { Point2d } from "../geometry3d/Point2dVector2d";
import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d";
import { Range1d, Range3d } from "../geometry3d/Range";
import { Transform } from "../geometry3d/Transform";
import { FacetFaceData } from "./FacetFaceData";
import { IndexedPolyfaceVisitor } from "./IndexedPolyfaceVisitor";
import { PolyfaceData } from "./PolyfaceData";
/**
 * A Polyface is an abstract mesh structure (of unspecified implementation) that provides a PolyfaceVisitor
 * to iterate over its facets.
 * @public
 */
export declare abstract class Polyface extends GeometryQuery {
    /** String name for schema properties */
    readonly geometryCategory = "polyface";
    /** Underlying polyface data. */
    data: PolyfaceData;
    /** Constructor */
    protected constructor(data: PolyfaceData);
    /**
     * Create and return a visitor for this concrete polyface.
     * @param numWrap the number of vertices to replicate in visitor arrays.
     */
    abstract createVisitor(numWrap: number): PolyfaceVisitor;
    /**
     * The [[PolyfaceData.twoSided]] flag.
     */
    get twoSided(): boolean;
    set twoSided(value: boolean);
    /**
     * Flag indicating if the mesh closure is unknown (0), open sheet (1), closed solid (2).
     * * A boundary edge of a mesh is defined as an edge with only one connected facet.
     * * Closed solid is a mesh with no boundary edge. Open sheet is a mesh that has boundary edge(s).
     */
    get expectedClosure(): number;
    set expectedClosure(value: number);
    /**
     * Check validity of indices into a data array.
     * * It is valid to have both indices and data undefined.
     * * It is NOT valid for just one to be defined.
     * * Index values at indices[indexPositionA <= i < indexPositionB] must be valid indices to the data array.
     * @param indices array of indices.
     * @param indexPositionA first index to test.
     * @param indexPositionB one past final index to test.
     * @param data data array.
     * @param dataLength length of data array.
     */
    static areIndicesValid(indices: number[] | undefined, indexPositionA: number, indexPositionB: number, data: any, dataLength: number): boolean;
    /** Returns true if this polyface has no facets. */
    abstract get isEmpty(): boolean;
    /** Returns the number of facets of this polyface. Subclasses should override. */
    get facetCount(): number | undefined;
}
/**
 * An `IndexedPolyface` is a set of facets which can have normal, param, and color arrays with independent point,
 * normal, param, and color indices.
 * @public
 */
export declare class IndexedPolyface extends Polyface {
    /**
     * Start indices of all facets of the polyface.
     * * Each element is an index to the `this.data.pointIndex` array entry for a specific facet.
     * * The facet count is `_facetStart.length - 1`.
     * * The face loop for the i_th facet consists of the entries in `this.data.pointIndex` at indices `_facetStart[i]`
     * up to (but not including) `_facetStart[i + 1]`.
     * * Note the array is initialized with one entry (value 0).
     */
    protected _facetStart: number[];
    /**
     * Index to the `this.data.face` array entry for a specific facet.
     * * `_facetToFaceData` has one entry per facet.
     */
    protected _facetToFaceData: number[];
    /**
     * Constructor for a new polyface.
     * @param data PolyfaceData arrays to capture.
     * @param facetStart optional array of facet start indices (e.g. known during clone)
     * @param facetToFacetData optional array of face identifiers (e.g. known during clone)
     */
    protected constructor(data: PolyfaceData, facetStart?: number[], facetToFaceData?: number[]);
    /** Given an edgeIndex (index into `data.pointIndex`), return the index of the facet containing the edge. */
    edgeIndexToFacetIndex(k: number | undefined): number | undefined;
    /**
     * Given an edgeIndex (index into `data.pointIndex`), return the range of the edgeIndices of the containing facet.
     * * If an edge with edgeIndex `k` is found in the facet with facetIndex `f`, then the returned range `r` satisfies
     * `r.low = this.facetIndex0(f) <= k < this.facetIndex1(f) = r.high` and can be used to iterate the facet's face
     * loop. See [[facetIndex0]].
     */
    edgeIndexToFaceLoop(k: number | undefined): Range1d | undefined;
    /** Test if other is an instance of `IndexedPolyface` */
    isSameGeometryClass(other: any): boolean;
    /** Tests for equivalence between two IndexedPolyfaces. */
    isAlmostEqual(other: any): boolean;
    /** Returns true if either the point array or the point index array is empty. */
    get isEmpty(): boolean;
    /**
     * Transform the mesh.
     * * If `transform` is a mirror, also reverse the index order around each facet.
     * * Note that this method always returns true. If transforming the normals fails (due to singular matrix or zero
     * normal), the original normal(s) are left unchanged.
     */
    tryTransformInPlace(transform: Transform): boolean;
    /** Reverse indices for a single facet. */
    reverseSingleFacet(facetId: number): void;
    /** Return a deep clone. */
    clone(): IndexedPolyface;
    /**
     * Return a deep clone with transformed points and normals.
     * @see [[IndexedPolyface.tryTransformInPlace]] for details of how transform is done.
     */
    cloneTransformed(transform: Transform): IndexedPolyface;
    /** Reverse the order of indices around all facets. */
    reverseIndices(): void;
    /** Reverse the direction of all normal vectors. */
    reverseNormals(): void;
    /**
     * Return face data using a facet index.
     * * Returns `undefined` if none found.
     * * This is the REFERENCE to the FacetFaceData not a copy.
    */
    tryGetFaceData(i: number): FacetFaceData | undefined;
    /**
     * Add facets from `source` to `this` polyface.
     * * Optionally reverse facet indices as per `PolyfaceData.reverseIndicesSingleFacet()` with `preserveStart = false` and
     * invert source normals.
     * * Optionally apply a `transform` to points and normals.
     * * Will only copy param, normal, color, and face data if we are already tracking them AND/OR the source contains them.
     */
    addIndexedPolyface(source: IndexedPolyface, reversed: boolean, transform: Transform | undefined): void;
    /**
     * Return the total number of indices in zero-terminated style, which includes
     * * all the indices in the packed zero-based table.
     * * one additional index for the zero-terminator of each facet.
     * @note Note that all index arrays (pointIndex, normalIndex, paramIndex, colorIndex) have the same counts, so there
     * is not a separate query for each of them.
     */
    get zeroTerminatedIndexCount(): number;
    /**
     * Create an empty facet set with coordinate and index data to be supplied later.
     * @param needNormals `true` to allocate empty normal data and index arrays; `false` (default) to leave undefined.
     * @param needParams `true` to allocate empty uv parameter data and index arrays; `false` (default) to leave undefined.
     * @param needColors `true` to allocate empty color data and index arrays; `false` (default) to leave undefined.
     * @param twoSided `true` (default) if the facets are to be considered viewable from the back; `false` if they are amenable to backface culling.
     */
    static create(needNormals?: boolean, needParams?: boolean, needColors?: boolean, twoSided?: boolean): IndexedPolyface;
    /**
     * Add (a clone of) a point to point array.
     * @param point the point.
     * @param priorIndex (optional) index of prior point to check for possible duplicate value.
     * @returns the zero-based index of the added or duplicate point.
     */
    addPoint(point: Point3d, priorIndex?: number): number;
    /**
     * Add a point to point array.
     * @param x the x coordinate of point.
     * @param y the y coordinate of point.
     * @param z the z coordinate of point.
     * @returns the zero-based index of the added point.
     */
    addPointXYZ(x: number, y: number, z: number): number;
    /**
     * Add (a clone of) a uv parameter to the parameter array.
     * @param param the parameter.
     * @returns zero-based index of the added param.
     */
    addParam(param: Point2d): number;
    /**
     * Add a uv parameter to the parameter array.
     * @param u the u part of parameter.
     * @param v the v part of parameter.
     * @param priorIndexA first index to check for possible duplicate value.
     * @param priorIndexB second index to check for possible duplicate value.
     * @returns zero-based index of the added or duplicate parameter.
     */
    addParamUV(u: number, v: number, priorIndexA?: number, priorIndexB?: number): number;
    /**
     * Add (a clone of) a normal vector to the normal array.
     * @param normal the normal vector.
     * @param priorIndexA first index to check for possible duplicate value.
     * @param priorIndexB second index to check for possible duplicate value.
     * @returns zero-based index of the added or duplicate normal.
     */
    addNormal(normal: Vector3d, priorIndexA?: number, priorIndexB?: number): number;
    /**
     * Add a normal vector to the normal array.
     * @param x the x coordinate of normal.
     * @param y the y coordinate of normal.
     * @param z the z coordinate of normal.
     * @returns zero-based index of the added normal vector.
     */
    addNormalXYZ(x: number, y: number, z: number): number;
    /**
     * Add a color to the color array
     * @param color the color.
     * @returns zero-based index of the added color.
     */
    addColor(color: number): number;
    /** Add a point index with edge visibility flag. */
    addPointIndex(index: number, visible?: boolean): void;
    /** Add a normal index. */
    addNormalIndex(index: number): void;
    /** Add a param index. */
    addParamIndex(index: number): void;
    /** Add a color index. */
    addColorIndex(index: number): void;
    /**
     * Clean up the open facet.
     * @deprecated in 4.5.0 - will not be removed until after 2026-06-13. To remove nebulous "open facet" concept from the API. Call [[PolyfaceData.trimAllIndexArrays]]
     * instead.
     */
    cleanupOpenFacet(): void;
    /**
     * Validate (the tail of) the active index arrays: point, normal, param, color.
     * @param index0 optional offset into the index arrays at which to start validating indices. Default 0.
     * @param errors optional array appended with error message(s) if invalid indices are encountered
     * @return whether the indices are valid
     */
    validateAllIndices(index0?: number, errors?: string[]): boolean;
    /**
     * Announce the end of construction of a facet.
     * * Optionally check for:
     *   * Same number of indices among all active index arrays -- point, normal, param, color
     *   * All indices for the latest facet are within bounds of the respective data arrays.
     * * In error cases, all index arrays are trimmed back to the size when previous facet was terminated.
     * * A return value of `undefined` is normal. Otherwise, a string array of error messages is returned.
     */
    terminateFacet(validateAllIndices?: boolean): string[] | undefined;
    /** Number of facets (read-only property). */
    get facetCount(): number;
    /** Number of faces (read-only property). */
    get faceCount(): number;
    /** Number of points (read-only property). */
    get pointCount(): number;
    /** Number of colors (read-only property). */
    get colorCount(): number;
    /** Number of parameters (read-only property). */
    get paramCount(): number;
    /** Number of normals (read-only property). */
    get normalCount(): number;
    /** Test if `index` is a valid facet index. */
    isValidFacetIndex(facetIndex: number): boolean;
    /** Return the number of edges in a particular facet. */
    numEdgeInFacet(facetIndex: number): number;
    /**
     * Given a valid facet index, return the index at which its face loop starts in the index arrays.
     * * A "face loop" is a contiguous block of indices into the parallel polyface index arrays.
     * * Each of these indices represents an edge of a facet, thus it is sometimes called an "edgeIndex".
     * * Together with [[facetIndex1]], this method can be used to iterate the face loop of the facet
     * with index `iFacet` as follows:
     * ````
     * for (let iEdge = this.facetIndex0(iFacet); iEdge < this.facetIndex1(iFacet); iEdge++) {
     *   const iPoint = this.data.pointIndex[iEdge];
     *   const p = this.data.point[iPoint];
     *   // ... process the edge of this facet starting at point p
     * }
     * ````
     */
    facetIndex0(facetIndex: number): number;
    /**
     * Given a valid facet index, return one past the index at which its face loop ends in the index arrays.
     * * For details, see [[facetIndex0]].
     */
    facetIndex1(facetIndex: number): number;
    /** Return a readonly reference to the facetStart array accessed by [[facetIndex0]] and [[facetIndex1]]. */
    get facetStart(): ReadonlyArray<number>;
    /** create a visitor for this polyface */
    createVisitor(numWrap?: number): IndexedPolyfaceVisitor;
    /** Extend `range` with coordinates from this mesh, optionally transformed. */
    extendRange(range: Range3d, transform?: Transform): void;
    /**
     * Given the index of a facet, return the data pertaining to the face it is a part of.
     * @deprecated in 4.5.0 - will not be removed until after 2026-06-13. Use [[IndexedPolyface.tryGetFaceData]], which verifies the index is in range.
     */
    getFaceDataByFacetIndex(facetIndex: number): FacetFaceData;
    /**
     * Set new FacetFaceData.
     * * All terminated facets since the last face declaration will be mapped to a single new FacetFaceData object using
     * facetToFaceData[]. FacetFaceData holds the 2D range of the face. Returns `true` if successful, `false` otherwise.
     */
    setNewFaceData(endFacetIndex?: number): boolean;
    /** Second step of double dispatch: call `handler.handleIndexedPolyface(this)`. */
    dispatchToGeometryHandler(handler: GeometryHandler): any;
    /** If the input accesses an edgeMateIndex array, return it along with the owning IndexedPolyface. */
    static hasEdgeMateIndex(polyface: Polyface | PolyfaceVisitor): {
        parent: IndexedPolyface;
        edgeMateIndex: Array<number | undefined>;
    } | undefined;
}
/**
 * A PolyfaceVisitor manages data while iterating facets.
 * * The polyface visitor holds data for one facet at a time.
 * * The caller can request the position in the addressed polyfaceData as a "readIndex".
 * * The readIndex values (as numbers) are not assumed to be sequential (i.e., they might be contiguous facet indices
 * or the indexing scheme might have gaps at the whim of the particular PolyfaceVisitor implementation).
 * * Example usage:
 * ```
 * const visitor = myPolyface.createVisitor();
 * for (visitor.reset(); visitor.moveToNextFacet(); ) {
 *   // process the current facet
 * }
 * ```
 * @public
 */
export interface PolyfaceVisitor extends PolyfaceData {
    /** Load data for the facet with given index. */
    moveToReadIndex(index: number): boolean;
    /** Return the index of the currently loaded facet. */
    currentReadIndex(): number;
    /** Load data for the next facet. */
    moveToNextFacet(): boolean;
    /** Restart the visitor at the first facet. */
    reset(): void;
    /** Return the point index of vertex i within the currently loaded facet. */
    clientPointIndex(i: number): number;
    /** Return the param index of vertex i within the currently loaded facet. */
    clientParamIndex(i: number): number;
    /** Return the normal index of vertex i within the currently loaded facet. */
    clientNormalIndex(i: number): number;
    /** Return the color index of vertex i within the currently loaded facet. */
    clientColorIndex(i: number): number;
    /** Return the aux data index of vertex i within the currently loaded facet. */
    clientAuxIndex(i: number): number;
    /** Return the client polyface. */
    clientPolyface(): Polyface | undefined;
    /**
     * Set the number of vertices replicated in visitor arrays (both data and index arrays).
     * * 0,1,2 are the most common values.
     * * Example: suppose `[6,7,8]` is the pointIndex array representing a triangle. First edge would be `6,7`. Second
     * edge is `7,8`. Third edge is `8,6`. To access `6` for the third edge, we have to go back to the start of array.
     * Therefore, it is useful to store `6` at the end of pointIndex array, i.e., `[6,7,8,6]` meaning `numWrap = 1`.
     * * Continuing this example, `numWrap = 2` (i.e., `[6,7,8,6,7]`) is useful when each vertex visit requires
     * the next two points, e.g., to form two adjacent vectors for a cross product.
     */
    setNumWrap(numWrap: number): void;
    /** Clear the contents of the data arrays. Use this along with `pushDataFrom` to build up new facets. */
    clearArrays(): void;
    /** Transfer data from a specified index of the other visitor as new data in this visitor. */
    pushDataFrom(other: PolyfaceVisitor, index: number): void;
    /**
     * Transfer interpolated data from the other visitor.
     * * All data values are interpolated at `fraction` between `other` values at `index0` and `index1`.
     */
    pushInterpolatedDataFrom(other: PolyfaceVisitor, index0: number, fraction: number, index1: number): void;
    /**
     * Return the number of facets this visitor is able to visit.
     * * Allows implementers to improve the efficiency of e.g., [[PolyfaceQuery.visitorClientFacetCount]].
     */
    getVisitableFacetCount?(): number;
    /** Create a visitor for a subset of the facets visitable by the instance. */
    createSubsetVisitor?(facetIndices: number[], numWrap: number): PolyfaceVisitor;
}
//# sourceMappingURL=Polyface.d.ts.map