import '../../../assert/js/assert.js';
import '../../../globals.js';
/**
 * A segment represents a specific curve with a start and end.
 *
 * Each segment is treated parametrically, where t=0 is the start of the segment, and t=1 is the end. Values of t
 * between those represent points along the segment.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import TEmitter from '../../../axon/js/TEmitter.js';
import Bounds2 from '../../../dot/js/Bounds2.js';
import Matrix3 from '../../../dot/js/Matrix3.js';
import Ray2 from '../../../dot/js/Ray2.js';
import Vector2 from '../../../dot/js/Vector2.js';
import KeysMatching from '../../../phet-core/js/types/KeysMatching.js';
import { Arc, Cubic, EllipticalArc, Line, Quadratic, RayIntersection, SegmentIntersection, SerializedArc, SerializedCubic, SerializedEllipticalArc, SerializedLine, SerializedQuadratic, Shape } from '../imports.js';
export type DashValues = {
    values: number[];
    arcLength: number;
    initiallyInside: boolean;
};
export type SerializedSegment = SerializedArc | SerializedCubic | SerializedEllipticalArc | SerializedLine | SerializedQuadratic;
type SimpleOverlap = {
    a: number;
    b: number;
};
type PossibleSimpleOverlap = SimpleOverlap | null | true;
export type ClosestToPointResult = {
    segment: Segment;
    t: number;
    closestPoint: Vector2;
    distanceSquared: number;
};
export type PiecewiseLinearOptions = {
    minLevels?: number;
    maxLevels?: number;
    distanceEpsilon?: number | null;
    curveEpsilon?: number | null;
    pointMap?: (v: Vector2) => Vector2;
    methodName?: KeysMatching<Segment, (options: PiecewiseLinearOptions) => Segment[]> | KeysMatching<Arc, (options: PiecewiseLinearOptions) => Segment[]> | KeysMatching<Cubic, (options: PiecewiseLinearOptions) => Segment[]> | KeysMatching<EllipticalArc, (options: PiecewiseLinearOptions) => Segment[]> | KeysMatching<Line, (options: PiecewiseLinearOptions) => Segment[]> | KeysMatching<Quadratic, (options: PiecewiseLinearOptions) => Segment[]>;
};
type PiecewiseLinearOrArcRecursionOptions = {
    curvatureThreshold: number;
    errorThreshold: number;
    errorPoints: [number, number];
};
type PiecewiseLinearOrArcOptions = {
    minLevels?: number;
    maxLevels?: number;
} & Partial<PiecewiseLinearOrArcRecursionOptions>;
export default abstract class Segment {
    invalidationEmitter: TEmitter;
    protected constructor();
    abstract get start(): Vector2;
    abstract get end(): Vector2;
    abstract get startTangent(): Vector2;
    abstract get endTangent(): Vector2;
    abstract get bounds(): Bounds2;
    abstract positionAt(t: number): Vector2;
    abstract tangentAt(t: number): Vector2;
    abstract curvatureAt(t: number): number;
    abstract subdivided(t: number): Segment[];
    abstract getSVGPathFragment(): string;
    abstract strokeLeft(lineWidth: number): Segment[];
    abstract strokeRight(lineWidth: number): Segment[];
    abstract windingIntersection(ray: Ray2): number;
    abstract getInteriorExtremaTs(): number[];
    abstract intersection(ray: Ray2): RayIntersection[];
    abstract getBounds(): Bounds2;
    abstract getSignedAreaFragment(): number;
    abstract getNondegenerateSegments(): Segment[];
    abstract writeToContext(context: CanvasRenderingContext2D): void;
    abstract transformed(matrix: Matrix3): Segment;
    abstract invalidate(): void;
    abstract serialize(): SerializedSegment;
    /**
     * Will return true if the start/end tangents are purely vertical or horizontal. If all of the segments of a shape
     * have this property, then the only line joins will be a multiple of pi/2 (90 degrees), and so all of the types of
     * line joins will have the same bounds. This means that the stroked bounds will just be a pure dilation of the
     * regular bounds, by lineWidth / 2.
     */
    areStrokedBoundsDilated(): boolean;
    /**
     * TODO: override everywhere so this isn't necessary (it's not particularly efficient!) https://github.com/phetsims/kite/issues/76
     */
    getBoundsWithTransform(matrix: Matrix3): Bounds2;
    /**
     * Extracts a slice of a segment, based on the parametric value.
     *
     * Given that this segment is represented by the interval [0,1]
     */
    slice(t0: number, t1: number): Segment;
    /**
     * @param tList - list of sorted t values from 0 <= t <= 1
     */
    subdivisions(tList: number[]): Segment[];
    /**
     * Return an array of segments from breaking this segment into monotone pieces
     */
    subdividedIntoMonotone(): Segment[];
    /**
     * Determines if the segment is sufficiently flat (given certain epsilon values)
     *
     * @param distanceEpsilon - controls level of subdivision by attempting to ensure a maximum (squared)
     *                          deviation from the curve
     * @param curveEpsilon - controls level of subdivision by attempting to ensure a maximum curvature change
     *                       between segments
     */
    isSufficientlyFlat(distanceEpsilon: number, curveEpsilon: number): boolean;
    /**
     * Returns the (sometimes approximate) arc length of the segment.
     */
    getArcLength(distanceEpsilon?: number, curveEpsilon?: number, maxLevels?: number): number;
    /**
     * Returns information about the line dash parametric offsets for a given segment.
     *
     * As always, this is fairly approximate depending on the type of segment.
     *
     * @param lineDash
     * @param lineDashOffset
     * @param distanceEpsilon - controls level of subdivision by attempting to ensure a maximum (squared)
     *                          deviation from the curve
     * @param curveEpsilon - controls level of subdivision by attempting to ensure a maximum curvature change
     *                       between segments
     */
    getDashValues(lineDash: number[], lineDashOffset: number, distanceEpsilon: number, curveEpsilon: number): DashValues;
    /**
     *
     * @param [options]
     * @param [minLevels] -   how many levels to force subdivisions
     * @param [maxLevels] -   prevent subdivision past this level
     * @param [segments]
     * @param [start]
     * @param [end]
     */
    toPiecewiseLinearSegments(options: PiecewiseLinearOptions, minLevels?: number, maxLevels?: number, segments?: Line[], start?: Vector2, end?: Vector2): Line[];
    /**
     * Returns a list of Line and/or Arc segments that approximates this segment.
     */
    toPiecewiseLinearOrArcSegments(providedOptions: PiecewiseLinearOrArcOptions): Segment[];
    /**
     * Helper function for toPiecewiseLinearOrArcSegments. - will push into segments
     */
    private toPiecewiseLinearOrArcRecursion;
    /**
     * Returns a Shape containing just this one segment.
     */
    toShape(): Shape;
    getClosestPoints(point: Vector2): ClosestToPointResult[];
    /**
     * List of results (since there can be duplicates), threshold is used for subdivision,
     * where it will exit if all of the segments are shorter than the threshold
     *
     * TODO: solve segments to determine this analytically! https://github.com/phetsims/kite/issues/76
     */
    static closestToPoint(segments: Segment[], point: Vector2, threshold: number): ClosestToPointResult[];
    /**
     * Given the cubic-premultiplied values for two cubic bezier curves, determines (if available) a specified (a,b) pair
     * such that p( t ) === q( a * t + b ).
     *
     * Given a 1-dimensional cubic bezier determined by the control points p0, p1, p2 and p3, compute:
     *
     * [ p0s ]    [  1   0   0   0 ]   [ p0 ]
     * [ p1s ] == [ -3   3   0   0 ] * [ p1 ]
     * [ p2s ] == [  3  -6   3   0 ] * [ p2 ]
     * [ p3s ]    [ -1   3  -3   1 ]   [ p3 ]
     *
     * see Cubic.getOverlaps for more information.
     */
    static polynomialGetOverlapCubic(p0s: number, p1s: number, p2s: number, p3s: number, q0s: number, q1s: number, q2s: number, q3s: number): PossibleSimpleOverlap;
    /**
     * Given the quadratic-premultiplied values for two quadratic bezier curves, determines (if available) a specified (a,b) pair
     * such that p( t ) === q( a * t + b ).
     *
     * Given a 1-dimensional quadratic bezier determined by the control points p0, p1, p2, compute:
     *
     * [ p0s ]    [  1   0   0 ]   [ p0 ]
     * [ p1s ] == [ -2   2   0 ] * [ p1 ]
     * [ p2s ]    [  2  -2   3 ] * [ p2 ]
     *
     * see Quadratic.getOverlaps for more information.
     */
    static polynomialGetOverlapQuadratic(p0s: number, p1s: number, p2s: number, q0s: number, q1s: number, q2s: number): PossibleSimpleOverlap;
    /**
     * Given the linear-premultiplied values for two lines, determines (if available) a specified (a,b) pair
     * such that p( t ) === q( a * t + b ).
     *
     * Given a line determined by the control points p0, p1, compute:
     *
     * [ p0s ] == [  1   0 ] * [ p0 ]
     * [ p1s ] == [ -1   1 ] * [ p1 ]
     *
     * see Quadratic/Cubic.getOverlaps for more information.
     */
    static polynomialGetOverlapLinear(p0s: number, p1s: number, q0s: number, q1s: number): PossibleSimpleOverlap;
    /**
     * Returns all the distinct (non-endpoint, non-finite) intersections between the two segments.
     */
    static intersect(a: Segment, b: Segment): SegmentIntersection[];
    /**
     * Returns a Segment from the serialized representation.
     */
    static deserialize(obj: SerializedSegment): Segment;
    /**
     * Determines if the start/middle/end points are representative of a sufficiently flat segment
     * (given certain epsilon values)
     *
     * @param start
     * @param middle
     * @param end
     * @param distanceEpsilon - controls level of subdivision by attempting to ensure a maximum (squared)
     *                          deviation from the curve
     * @param curveEpsilon - controls level of subdivision by attempting to ensure a maximum curvature change
     *                       between segments
     */
    static isSufficientlyFlat(distanceEpsilon: number, curveEpsilon: number, start: Vector2, middle: Vector2, end: Vector2): boolean;
    static filterClosestToPointResult(results: ClosestToPointResult[]): ClosestToPointResult[];
}
export {};
//# sourceMappingURL=Segment.d.ts.map