/**
 * The {@link CoordQuad} positions nodes to minimize a quadratic
 * optimization.
 *
 * @packageDocumentation
 */
import type { GraphLink, GraphNode } from "../../graph";
import { type U } from "../../utils";
import type { Coord } from ".";
/**
 * a strictly callable {@link NodeWeight}
 */
export type CallableNodeWeight<NodeDatum = never, LinkDatum = never> = (node: GraphNode<NodeDatum, LinkDatum>) => number;
/**
 * an accessor to get the optimization of the weight for a node
 *
 * Currently this is only used to set the {@link CoordQuad#nodeCurve}.
 */
export type NodeWeight<NodeDatum = never, LinkDatum = never> = number | CallableNodeWeight<NodeDatum, LinkDatum>;
/**
 * a strictly callable {@link LinkWeight}
 */
export type CallableLinkWeight<NodeDatum = never, LinkDatum = never> = (link: GraphLink<NodeDatum, LinkDatum>) => number;
/**
 * an accessor to get the optimization of the weight for a link
 *
 * Currently this is used to set the following accessors:
 * {@link CoordQuad#linkCurve}, {@link CoordQuad#vertWeak},
 * {@link CoordQuad#vertStrong}.
 */
export type LinkWeight<NodeDatum = never, LinkDatum = never> = number | CallableLinkWeight<NodeDatum, LinkDatum>;
/** the operators for the quad operator */
export interface CoordQuadOps<N = never, L = never> {
    /** the vert weak accessor */
    vertWeak: LinkWeight<N, L>;
    /** the vert strong accessor */
    vertStrong: LinkWeight<N, L>;
    /** the link weight accessor */
    linkCurve: LinkWeight<N, L>;
    /** the node weight accessor */
    nodeCurve: NodeWeight<N, L>;
}
/** node datum for operators */
export type OpNodeDatum<O extends CoordQuadOps> = O extends CoordQuadOps<infer N, never> ? N : never;
/** link datum for operators */
export type OpLinkDatum<O extends CoordQuadOps> = O extends CoordQuadOps<never, infer L> ? L : never;
/**
 * a {@link Coord} that places nodes to minimize a quadratic function
 *
 * This operators generally takes the longest of all built-in operators but
 * produces a pleasing layout.
 *
 * Create with {@link coordQuad}.
 */
export interface CoordQuad<Ops extends CoordQuadOps> extends Coord<OpNodeDatum<Ops>, OpLinkDatum<Ops>> {
    /**
     * set the weak vertical accessor.
     *
     * The weak vertical accessor adds a penalty to make edges vertical. It's
     * weak in that it applies to all edges equally regardless of length, and
     * while it penalized non vertical edges, it allows curving in the middle of
     * long edges.
     *
     * (default: `1`)
     */
    vertWeak<NewVertWeak extends LinkWeight>(val: NewVertWeak): CoordQuad<U<Ops, "vertWeak", NewVertWeak>>;
    /**
     * get the current vertWeak accessor
     */
    vertWeak(): Ops["vertWeak"];
    /**
     * set the strong vertical accessor.
     *
     * The strong vertical accessor adds a penalty to make edges vertical. It
     * penealizes any section of an edge that isn't vertical, making longer edges
     * contribute more to the overall impact on the objective.
     *
     * (default: `0`)
     */
    vertStrong<NewVertStrong extends LinkWeight>(val: NewVertStrong): CoordQuad<U<Ops, "vertStrong", NewVertStrong>>;
    /**
     * get the current vertStrong accessor
     */
    vertStrong(): Ops["vertStrong"];
    /**
     * set the link curve weight accessor
     *
     * The link curve weight penalizes links to reduce their curving, in
     * dependent of their verticality. If using strongVert for an edge, it
     * probably won't need a strong link curve weight.
     *
     * (default: `1`)
     */
    linkCurve<NewLinkCurve extends LinkWeight>(val: NewLinkCurve): CoordQuad<U<Ops, "linkCurve", NewLinkCurve>>;
    /**
     * get the current link curve weight accessor
     */
    linkCurve(): Ops["linkCurve"];
    /**
     * set the node curve weight accessor
     *
     * The node curve weight penalizes curves through nodes. If a node only has
     * one incoming and one outgoing edge, it will try to make them match in
     * angle. Note that it does it for all possible "through edges" so multiple
     * incoming and multiple outgoing will get counted several times. It's not
     * clear why this would ever be desirable, but it's possible to specify.
     *
     * (default: `0`)
     */
    nodeCurve<NewNodeCurve extends NodeWeight>(val: NewNodeCurve): CoordQuad<U<Ops, "nodeCurve", NewNodeCurve>>;
    /**
     * get the current node curve accessor
     */
    nodeCurve(): Ops["nodeCurve"];
    /**
     * set the weight for how close nodes should be to zero.
     *
     * This ensures the optimization is sound, and is necessary if there are
     * certain types of disconnected components or zero weights for different
     * curvature constraints. If the graph is connected and the weights are
     * positive this can be set to zero, otherwise it should be positive, but
     * small.
     *
     * (default: `1e-6`)
     */
    compress(val: number): CoordQuad<Ops>;
    /** get the current compress weight. */
    compress(): number;
    /** @internal flag indicating that this is built in to d3dag and shouldn't error in specific instances */
    readonly d3dagBuiltin: true;
}
/** default quad operator */
export type DefaultCoordQuad = CoordQuad<{
    /** default vert weak */
    vertWeak: 1;
    /** default vert strong */
    vertStrong: 0;
    /** default link curve */
    linkCurve: 1;
    /** default node curve */
    nodeCurve: 0;
}>;
/**
 * create a default {@link CoordQuad}
 *
 * This coordinate assignment operator tries to minimize the curve of links.
 * Unlike {@link coordSimplex} it produces layouts with less verticality, which
 * often look a little worse.
 *
 * @example
 *
 * ```ts
 * const layout = sugiyama().coord(coordQuad().vertStrong(1));
 * ```
 */
export declare function coordQuad(...args: never[]): DefaultCoordQuad;
