/** @packageDocumentation
 * @module CartesianGeometry
 */
import { Arc3d } from "../curve/Arc3d";
import { CurveChain } from "../curve/CurveCollection";
import { AnnounceNumberNumber, AnnounceNumberNumberCurvePrimitive, CurvePrimitive } from "../curve/CurvePrimitive";
import { AnyCurve, AnyRegion } from "../curve/CurveTypes";
import { GeometryQuery } from "../curve/GeometryQuery";
import { StrokeOptions } from "../curve/StrokeOptions";
import { GrowableFloat64Array } from "../geometry3d/GrowableFloat64Array";
import { GrowableXYZArray } from "../geometry3d/GrowableXYZArray";
import { IndexedXYZCollection } from "../geometry3d/IndexedXYZCollection";
import { Plane3dByOriginAndUnitNormal } from "../geometry3d/Plane3dByOriginAndUnitNormal";
import { Point3d } from "../geometry3d/Point3dVector3d";
import { Range1d, Range3d } from "../geometry3d/Range";
import { GrowableXYZArrayCache } from "../geometry3d/ReusableObjectCache";
import { Transform } from "../geometry3d/Transform";
import { LowAndHighXY, XAndY } from "../geometry3d/XYZProps";
import { ClipPlane } from "./ClipPlane";
import { ClipPrimitive } from "./ClipPrimitive";
import { ClipVector } from "./ClipVector";
import { ConvexClipPlaneSet } from "./ConvexClipPlaneSet";
import { UnionOfConvexClipPlaneSets } from "./UnionOfConvexClipPlaneSets";
/**
 * Enumerated type for describing where geometry lies with respect to clipping planes.
 * @public
 */
export declare enum ClipPlaneContainment {
    /** All points inside. */
    StronglyInside = 1,
    /** Inside/outside state unknown. */
    Ambiguous = 2,
    /** All points outside. */
    StronglyOutside = 3
}
/**
 * Enumeration of ways to handle an intermediate fragment from a clipping step.
 * @public
 */
export declare enum ClipStepAction {
    /** Pass fragments directly to final accepted "in" state. */
    acceptIn = 1,
    /** Pass fragments directly to final accepted "out" state. */
    acceptOut = -1,
    /** Forward fragments to subsequent steps. */
    passToNextStep = 0
}
/**
 * Enumerated type for describing what must yet be done to clip a piece of geometry.
 * @public
 */
export declare enum ClipStatus {
    /** Some geometry may cross the clip boundaries */
    ClipRequired = 0,
    /** Geometry is clearly outside */
    TrivialReject = 1,
    /** Geometry is clearly inside */
    TrivialAccept = 2
}
/**
 * An object containing clipping planes that can be used to clip geometry.
 * @public
 */
export interface Clipper {
    /** Test if `point` is on or inside the Clipper's volume. */
    isPointOnOrInside(point: Point3d, tolerance?: number): boolean;
    /**
     * Find the parts of the line segment (if any) that is within the convex clip volume.
     * * The line segment is defined by `pointA` and `pointB`.
     * * The input fractional interval from `fraction0` to `fraction1` (increasing) is the active part to consider.
     * * To clip to the usual bounded line segment, start with fractions (0,1).
     * If the clip volume is unbounded, the line interval may also be unbounded.
     * * An unbounded line portion will have fraction coordinates positive or negative `Number.MAX_VALUE`.
     * @param f0 fraction that is the initial lower fraction of the active interval (e.g., 0.0 for bounded segment).
     * @param f1 fraction that is the initial upper fraction of the active interval (e.g., 1.0 for bounded segment).
     * @param pointA segment start (fraction 0)
     * @param pointB segment end (fraction 1)
     * @param announce function to be called to announce a fraction interval that is within the convex clip volume.
     * @returns true if a segment was announced, false if entirely outside.
     */
    announceClippedSegmentIntervals(f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: AnnounceNumberNumber): boolean;
    /**
     * Find the portion (or portions) of the arc (if any) that are within the convex clip volume.
     * @param arc the arc to be clipped.
     * @param announce function to be called to announce a fraction intervals that are within the convex clip volume.
     * @returns true if one or more arcs portions were announced, false if entirely outside.
     */
    announceClippedArcIntervals(arc: Arc3d, announce?: AnnounceNumberNumberCurvePrimitive): boolean;
    /**
     * Optional polygon clip method.
     * * This is expected to be implemented by planar clip structures.
     * * This is unimplemented for curve clippers (e.g. sphere) for which polygon clip result has curved edges.
     * * The input polygon must be convex.
     */
    appendPolygonClip?: AppendPolygonClipFunction;
}
/**
 * Signature of method to execute polygon clip, distributing fragments of xyz among insideFragments and outsideFragments
 * @param xyz convex polygon. This is not changed.
 * @param insideFragments Array to receive "inside" fragments. Each fragment is a GrowableXYZArray grabbed from
 * the cache. This is NOT cleared.
 * @param outsideFragments Array to receive "outside" fragments. Each fragment is a GrowableXYZArray grabbed from
 * the cache. This is NOT cleared.
 * @param arrayCache cache for reusable GrowableXYZArray.
 */
type AppendPolygonClipFunction = (xyz: IndexedXYZCollection, insideFragments: GrowableXYZArray[], outsideFragments: GrowableXYZArray[], arrayCache: GrowableXYZArrayCache) => void;
/**
 * Interface for clipping convex polygons.
 * Supported by:
 * * AlternatingCCTreeNode
 * * ConvexClipPlaneSet
 * @public
 */
export interface PolygonClipper {
    appendPolygonClip: AppendPolygonClipFunction;
}
/**
 * Class whose various static methods are functions for clipping geometry
 * @public
 */
export declare class ClipUtilities {
    private static _workTransform?;
    private static _workRange?;
    private static _workClipper?;
    private static _selectIntervals01TestPoint;
    /**
     * Augment the unsortedFractionsArray with 0 and 1
     * * sort
     * * test the midpoint of each interval with `clipper.isPointOnOrInside`
     * * pass accepted intervals to `announce(f0,f1,curve)`
     */
    static selectIntervals01(curve: CurvePrimitive, unsortedFractions: GrowableFloat64Array, clipper: Clipper, announce?: AnnounceNumberNumberCurvePrimitive): boolean;
    /**
     * Announce triples of (low, high, cp) for each entry in intervals.
     * @param intervals source array
     * @param cp CurvePrimitive for announcement
     * @param announce function to receive data
     */
    static announceNNC(intervals: Range1d[], cp: CurvePrimitive, announce?: AnnounceNumberNumberCurvePrimitive): boolean;
    /**
     * Compute and return portions of the input curve that are within the clipper.
     * @param curve input curve, unmodified
     * @param clipper used to compute the clipped components
     * @return array of clipped curves
     */
    static collectClippedCurves(curve: CurvePrimitive, clipper: Clipper): CurvePrimitive[];
    /**
     * Compute and return the portions of the input region that are within the clipper.
     * @param region input region, unmodified
     * @param clipper used to compute the clipped components
     * @return clipped subregion, as a single `AnyRegion`
     */
    static clipAnyRegion(region: AnyRegion, clipper: Clipper): AnyRegion | undefined;
    /**
     * Compute and return portions of the input curve or region that are within the clipper.
     * @param curve input curve or region, unmodified
     * @param clipper used to compute the clipped components
     * @return array of clipped components of the input curve or region that lie inside the clipper
     */
    static clipAnyCurve(curve: AnyCurve, clipper: Clipper): AnyCurve[];
    /**
     * Clip a polygon down to regions defined by each shape of a ClipShape.
     * @return An multidimensional array of points, where each array is the boundary of part of the remaining polygon.
     */
    static clipPolygonToClipShape(polygon: Point3d[], clipShape: ClipPrimitive): Point3d[][];
    /**
     * Clip a polygon down to regions defined by each shape of a ClipShape.
     * @return An multidimensional array of points, where each array is the boundary of part of the remaining polygon.
     */
    static clipPolygonToClipShapeReturnGrowableXYZArrays(polygon: Point3d[], clipShape: ClipPrimitive): GrowableXYZArray[];
    /**
     * Given an array of points, test for trivial containment conditions.
     * * ClipStatus.TrivialAccept if all points are in any one of the convexSet's.
     * * ClipStatus.ClipRequired if (in any single convexSet) there were points on both sides of any single plane.
     * * ClipStatus.TrivialReject if neither of those occurred.
     */
    static pointSetSingleClipStatus(points: GrowableXYZArray, planeSet: UnionOfConvexClipPlaneSets, tolerance: number): ClipStatus;
    /**
     * Emit point loops for intersection of a convex set with a range.
     * * return zero length array for (a) null range or (b) no intersections
     * @param range range to intersect
     * @param includeConvexSetFaces if false, do not compute facets originating as convex set planes.
     * @param includeRangeFaces if false, do not compute facets originating as range faces
     * @param ignoreInvisiblePlanes if true, do NOT compute a facet for convex set faces marked invisible.
     */
    static announceLoopsOfConvexClipPlaneSetIntersectRange(convexSet: ConvexClipPlaneSet | ClipPlane, range: Range3d, loopFunction: (loopPoints: GrowableXYZArray) => void, includeConvexSetFaces?: boolean, includeRangeFaces?: boolean, ignoreInvisiblePlanes?: boolean): void;
    /**
     * Return a (possibly empty) array of geometry (Loops !!) which are facets of the intersection of the convex set
     * intersecting a range.
     * * Return zero length array for (a) null range or (b) no intersections
     * @param allClippers convex or union clipper
     * @param range range to intersect
     * @param includeConvexSetFaces if false, do not compute facets originating as convex set planes.
     * @param includeRangeFaces if false, do not compute facets originating as range faces
     * @param ignoreInvisiblePlanes if true, do NOT compute a facet for convex set faces marked invisible.
     */
    static loopsOfConvexClipPlaneIntersectionWithRange(allClippers: ConvexClipPlaneSet | UnionOfConvexClipPlaneSets | ClipPlane, range: Range3d, includeConvexSetFaces?: boolean, includeRangeFaces?: boolean, ignoreInvisiblePlanes?: boolean): GeometryQuery[];
    /**
     * Return the (possibly null) range of the intersection of the convex set with a range.
     * * The convex set is permitted to be unbounded (e.g. a single plane).  The range parameter provides bounds.
     * @param convexSet convex set for intersection.
     * @param range range to intersect
     */
    static rangeOfConvexClipPlaneSetIntersectionWithRange(convexSet: ConvexClipPlaneSet, range: Range3d): Range3d;
    /**
     * Return the range of various types of clippers
     * * `ConvexClipPlaneSet` -- dispatch to `rangeOfConvexClipPlaneSetIntersectionWithRange`
     * * `UnionOfConvexClipPlaneSet` -- union of ranges of member `ConvexClipPlaneSet`
     * * `ClipPrimitive` -- access its `UnionOfConvexClipPlaneSet`.
     * * `ClipVector` -- intersection of the ranges of its `ClipPrimitive`.
     * * `undefined` -- entire input range.
     * * If `observeInvisibleFlag` is false, the "invisible" properties are ignored, and this effectively returns the range of the edge work of the members
     * * If `observeInvisibleFlag` is true, the "invisible" properties are observed, and "invisible" parts do not restrict the range.
     * @param clipper
     * @param range non-null range.
     * @param observeInvisibleFlag indicates how "invisible" bit is applied for ClipPrimitive.
     */
    static rangeOfClipperIntersectionWithRange(clipper: ConvexClipPlaneSet | UnionOfConvexClipPlaneSets | ClipPrimitive | ClipVector | undefined, range: Range3d, observeInvisibleFlag?: boolean): Range3d;
    /**
     * Test if various types of clippers have any intersection with a range.
     * * This follows the same logic as `rangeOfClipperIntersectionWithRange` but attempts to exit at earliest point of confirmed intersection
     * * `ConvexClipPlaneSet` -- dispatch to `doesConvexClipPlaneSetIntersectRange`
     * * `UnionOfConvexClipPlaneSet` -- union of ranges of member `ConvexClipPlaneSet`
     * * `ClipPrimitive` -- access its `UnionOfConvexClipPlaneSet`.
     * * `ClipVector` -- intersection of the ranges of its `ClipPrimitive`.
     * * `undefined` -- entire input range.
     * * If `observeInvisibleFlag` is false, the "invisible" properties are ignored, and holes do not affect the result.
     * * If `observeInvisibleFlag` is true, the "invisible" properties are observed, and may affect the result.
     * @param clipper
     * @param range non-null range.
     * @param observeInvisibleFlag indicates how "invisible" bit is applied for ClipPrimitive.
     */
    static doesClipperIntersectRange(clipper: ConvexClipPlaneSet | UnionOfConvexClipPlaneSets | ClipPrimitive | ClipVector | undefined, range: Range3d, observeInvisibleFlag?: boolean): boolean;
    /**
     * Emit point loops for intersection of a convex set with a range.
     * * return zero length array for (a) null range or (b) no intersections
     * @param range range to intersect
     * @param includeConvexSetFaces if false, do not compute facets originating as convex set planes.
     * @param includeRangeFaces if false, do not compute facets originating as range faces
     * @param ignoreInvisiblePlanes if true, do NOT compute a facet for convex set faces marked invisible.
     */
    static doesConvexClipPlaneSetIntersectRange(convexSet: ConvexClipPlaneSet, range: Range3d, includeConvexSetFaces?: boolean, includeRangeFaces?: boolean, ignoreInvisiblePlanes?: boolean): boolean;
    /**
     * Create a clipper from the transformed range.
     * @param range input range to create clipper from
     * @param transform how to transform the range (NOTE: applied to the range faces without swelling the range volume)
     * @param degeneratePoints optionally populated with the 1 or 2 points defining the transformed range if it is degenerate (all points colinear/coincident); otherwise untouched
     * @returns newly constructed clipper. If no clip planes could be computed, fill `degeneratePoints` and return undefined.
    */
    private static createClipperFromTransformedRange3d;
    /**
     * Handle pathological cases of range-range intersection, where one of the ranges defines no area or volume (is a line segment or single point).
     * @param range local range to intersect with the point/segment
     * @param points isolated local point, or local segment's start and end
     * @param localToWorld optional transform for output range
     * @param intersection optional range of the intersection, in world coordinates, or null range if no intersection.
     * @returns whether the point/segment intersects the range
     */
    private static rangeIntersectPointOrSegment;
    /**
     * Test for intersection of two ranges in different local coordinates.
     * * Useful for clash detection of elements in iModels, using their stored (tight) local ranges and placement transforms.
     * @param range0 first range in local coordinates
     * @param local0ToWorld placement transform for first range
     * @param range1 second range in local coordinates
     * @param local1ToWorld placement transform for second range. Assumed to be invertible.
     * @param range1Margin optional signed local distance to expand/contract the second range before intersection. Positive expands.
     * @return whether the local ranges are adjacent or intersect. Also returns false if local1ToWorld is singular.
     */
    static doLocalRangesIntersect(range0: Range3d, local0ToWorld: Transform, range1: Range3d, local1ToWorld: Transform, range1Margin?: number): boolean;
    /**
     * Compute the range of the intersection between two local (e.g., element-aligned) ranges.
     * @param range0 first range in local coordinates
     * @param local0ToWorld placement transform for first range
     * @param range1 second range in local coordinates
     * @param local1ToWorld placement transform for second range. Assumed to be invertible.
     * @param result optional pre-allocated range to fill and return
     * @return range of the intersection (aligned to world axes). Returns null range if local1ToWorld is singular.
     */
    static rangeOfIntersectionOfLocalRanges(range0: Range3d, local0ToWorld: Transform, range1: Range3d, local1ToWorld: Transform, result?: Range3d): Range3d;
    /**
     * Test if `obj` is a `Clipper` object.
     * * This is implemented by testing for each of the methods in the `Clipper` interface.
     */
    static isClipper(obj: any): boolean;
    /**
     * Specialized logic for replacing clip fragments by an equivalent singleton.
     * * If there are baseCount + 1 or fewer fragments, do nothing.
     * * If there are more than baseCount+1 fragments:
     *   * drop them all to the cache
     *   * push a copy of the singleton.
     * * The use case for this is that a multi-step clipper (e.g. UnionOfConvexClipPlaneSets) may produce many fragments,
     * and then be able to determine that they really are the original pre-clip polygon unchanged.
     * * The baseCount+1 case is the case where the entire original singleton is still a singleton and can be left alone.
     * * Calling this replacer shuffles the original back into the fragment array, and drops the fragments.
     * * This determination is solely within the logic of the caller.
     * @param shards array of fragments
     * @param baseCount original count
     * @param singleton single array which may be a replacement for multiple fragments
     * @param cache cache for array management
     */
    static restoreSingletonInPlaceOfMultipleShards(fragments: GrowableXYZArray[] | undefined, baseCount: number, singleton: IndexedXYZCollection, arrayCache: GrowableXYZArrayCache): void;
    /**
     * Create a UnionOfConvexClipPlaneSets for a volume defined by a path and offsets.
     * @param points points along the path.
     * @param positiveOffsetLeft offset to left.  0 is clip on the path.
     * @param positiveOffsetRight offset to the right.  0 is clip on the path.
     * @param z0 z for lower clipping plane.  If undefined, unbounded in positive z
     * @param z1 z for upper clipping plane.  If undefined, unbounded in negative z.
     * @alpha
     */
    static createXYOffsetClipFromLineString(points: Point3d[] | IndexedXYZCollection, leftOffset: number, rightOffset: number, z0: number, z1: number): UnionOfConvexClipPlaneSets;
    /** If data.length >= minLength threshold, push it to destination; if smaller drop it back to the cache. */
    static captureOrDrop(data: GrowableXYZArray, minLength: number, destination: GrowableXYZArray[], cache: GrowableXYZArrayCache): void;
    /**
     * Find the portion of a line within a half-plane clip.
     * * The half-plane clip is to the left of the line from clipA to clipB.
     * * The original clipped segment has fractions 0 and 1 at respective segment points.
     * * Caller initializes the interval
     * * This method reduces the interval size.
     * * See clipSegmentToCCWTriangleXY for typical use.
     * @param linePointA First point of clip line
     * @param linePointB Second point of clip line
     * @param segmentPoint0 First point of clipped segment
     * @param segmentPoint1 Second point of clipped segment
     * @param interval Live interval.
       * @param absoluteTolerance absolute tolerance for both cross product values to indicate "on" the line
     */
    static clipSegmentToLLeftOfLineXY(linePointA: XAndY, linePointB: XAndY, segmentPoint0: XAndY, segmentPoint1: XAndY, interval: Range1d, absoluteTolerance?: number): void;
    /**
     * Clip an interval of a line segment to a triangle.
     * * Triangle is assumed CCW
     * @param pointA point of triangle.
     * @param pointB point of triangle.
     * @param pointC point of triangle.
     * @param segment0 start of segment
     * @param segment1 end of segment
     * @param interval Pre-initialized interval of live part of segment
     * @param absoluteTolerance absolute tolerance for begin "on a line"
     */
    static clipSegmentToCCWTriangleXY(pointA: XAndY, pointB: XAndY, pointC: XAndY, segment0: XAndY, segment1: XAndY, interval: Range1d, absoluteTolerance?: number): void;
    /**
     * Find the portion of a line within a half-plane clip.
     * * The half-plane clip is to the left of the line from clipA to clipB.
     * * The original clipped segment has fractions 0 and 1 at respective segment points.
     * * Caller initializes the interval
     * * This method reduces the interval size.
     * * See clipSegmentToCCWTriangleXY for typical use.
     * @param linePointA First point of clip line
     * @param linePointB Second point of clip line
     * @param segmentPoint0 First point of clipped segment
     * @param segmentPoint1 Second point of clipped segment
     * @param interval Live interval.
       * @param absoluteTolerance absolute tolerance for both cross product values to indicate "on" the line
     */
    static clipSegmentBelowPlaneXY(plane: Plane3dByOriginAndUnitNormal, segmentPoint0: XAndY, segmentPoint1: XAndY, interval: Range1d, absoluteTolerance?: number): void;
    /**
     * Clip an interval of a line segment to an array of planes
     * * plane normals assumed OUTWARD
     * * planeAltitude is typically a tolerance a tolerance distance.
     *   * positive altitude makes tha plane move in the direction of the unit normal.
     * @param planes array of planes
     * @param segment0 start of segment
     * @param segment1 end of segment
     * @param interval Pre-initialized interval of live part of segment
     * @param absoluteTolerance absolute tolerance for begin "on a line"
     */
    static clipSegmentBelowPlanesXY(planes: Plane3dByOriginAndUnitNormal[], segment0: XAndY, segment1: XAndY, interval: Range1d, signedAltitude?: number): void;
    /**
     * Pass line segments from a polyline to the clipper.  Resolve the fractional clips to simple points for announcement.
     * @param clipper clipper to call
     * @param points polyline whose segments are passed to the clipper
     * @param announce caller's handler for simple point pairs.
     */
    static announcePolylineClip(clipper: Clipper, points: Point3d[], announce: (point0: Point3d, point1: Point3d) => void): void;
    /**
     * Pass line segments from a polyline to the clipper.  Sum the lengths of the clipped pieces.  Return the sum.
     * @param clipper clipper to call
     * @param points polyline whose segments are passed to the clipper
     */
    static sumPolylineClipLength(clipper: Clipper, points: Point3d[]): number;
    /**
     * Pass polygon `xyz` through a sequence of PolygonClip steps.
     * * At the outset, `xyz` is the (only) entry in a set of candidates.
     * * For each clipper, each candidate is presented for appendPolygon to inside and outside parts.
     * * Each (in,out) result is distributed among (acceptedIn, acceptedOut, candidates) according to
     *      (inAction, outAction)
     * * At the end, all remaining candidates are distributed among (acceptedIn, acceptedOut, finalUnknown)
     *     according to finalAction
     * * Any clipper that does not have an appendPolygonClip method is skipped.
     * @param xyz
     * @param clippers
     * @param acceptedIn
     * @param acceptedOut
     * @param finalCandidates
     * @param inAction
     * @param outAction
     * @param finalCandidateAction
     */
    static doPolygonClipSequence(xyz: IndexedXYZCollection, clippers: Clipper[], acceptedIn: GrowableXYZArray[] | undefined, acceptedOut: GrowableXYZArray[] | undefined, finalCandidates: GrowableXYZArray[] | undefined, inAction: ClipStepAction, outAction: ClipStepAction, finalFragmentAction: ClipStepAction, arrayCache: GrowableXYZArrayCache | undefined): void;
    /** Pass polygon `xyz` through a sequence of PolygonClip steps with "parity" rules */
    static doPolygonClipParitySequence(xyz: IndexedXYZCollection, clippers: Clipper[], acceptedIn: GrowableXYZArray[] | undefined, acceptedOut: GrowableXYZArray[] | undefined, arrayCache: GrowableXYZArrayCache | undefined): void;
    /**
     * For each plane of clipper, construct a UnionOfConvexClipPlaneSets for an outer (infinite) convex volume that
     * abuts the outer volume of the neighbor faces.
     */
    static createComplementaryClips(clipper: ConvexClipPlaneSet): UnionOfConvexClipPlaneSets;
    /**
     * Creates clippers for regions closest to the children of a curve chain.
     * * For best results, each child should have length larger than `distanceTol`.
     * @param curveChain A curve chain; xy-only (z-coordinate is ignored). Must have at least 2 children.
     * @param strokeOptions Optional stroke options to control the sampling of the curve chain.
     * @param distanceTol Optional distance tolerance to use when comparing points; default is [[Geometry.smallMetricDistance]].
     * @param boundingBox Optional nominal xy-bounding box for the clipper regions; default is maximal clipper regions.
     * @returns An ordered array of clippers, each of which represents the region closest to the corresponding primitive in the
     * input chain, or undefined if the input is invalid.
     */
    static createClippersForRegionsClosestToCurvePrimitivesXY(curveChain: CurveChain, strokeOptions?: StrokeOptions, distanceTol?: number, boundingBox?: LowAndHighXY): UnionOfConvexClipPlaneSets[] | undefined;
}
export {};
//# sourceMappingURL=ClipUtils.d.ts.map