UNPKG

d3-dag

Version:

Layout algorithms for visualizing directed acylic graphs.

114 lines (113 loc) 4.77 kB
/** * A {@link DecrossTwoLayer} heuristic for reducing the number of crossings in * large dags efficiently. * * @packageDocumentation */ import { Decross } from "."; import { U } from "../../utils"; import { Twolayer } from "../twolayer"; import { TwolayerAgg } from "../twolayer/agg"; import { TwolayerGreedy } from "../twolayer/greedy"; import { DecrossDfs } from "./dfs"; /** two layer operators */ export interface DecrossTwoLayerOps<N = never, L = never> { /** the order operator */ order: Twolayer<N, L>; /** the initializers */ inits: readonly Decross<N, L>[]; } /** * a decrossing operator that reorders by looking at pairs of layers * * This method can be very fast and is a general heuristic for efficient * minimization. Customize with a two layer operator with {@link order}, * different {@link inits}, or the number of {@link passes}. */ export interface DecrossTwoLayer<Ops extends DecrossTwoLayerOps = DecrossTwoLayerOps> extends Decross<Ops extends DecrossTwoLayerOps<infer N, never> ? N : never, Ops extends DecrossTwoLayerOps<never, infer L> ? L : never> { /** * sets the {@link Twolayer} accessor for minimizing a layer at a time * * The {@link Twolayer} operator takes pairs of layers, and reorders one. * There are three built-in variants: * - {@link twolayerGreedy} - This takes another two-layer operator, runs it, * and then afterwards performs greedy swaps of nodes to reduce the number * of edge crossings further. While not perfect, it can improve the results * of simpler heuristics. * - {@link twolayerAgg} - This aggregates the indices of ancestor nodes and * orders nodes according to those aggregates. This is very fast and * produces a good first-order decrossing, but is best when used in * conjunction with {@link twolayerGreedy}. * - {@link twolayerOpt} - This is the sibling to {@link decrossOpt} that * only optimizes a single layer, but otherwise has similar options. Just * like full optimal decrossing, this will fail on large graphs, but also * rarely produces better results than the combination of {@link * twolayerGreedy} and {@link twolayerAgg}. * * (default: {@link twolayerGreedy}) */ order<NewOrder extends Twolayer>(val: NewOrder): DecrossTwoLayer<U<Ops, "order", NewOrder>>; /** * get the current {@link Twolayer} for ordering */ order(): Ops["order"]; /** * sets the initialization passes before decrossings * * For every initialization operator, this will run the two layer heuristic, * ultimately choosing the ordering that minimized overall crossings. For * this reason, only quick decrossing operators should be used, not expensive * ones. The empty list is treated as a singleton list with a noop operator. * * (default: `[decrossDfs(), decrossDfs().topDown(false)]`) */ inits<const NewInits extends readonly Decross[]>(val: NewInits): DecrossTwoLayer<U<Ops, "inits", NewInits>>; /** * get the current initialization passes */ inits(): Ops["inits"]; /** * sets the number of passes to make * * More passes may take longer, but might result in a better output. * * (default: `24`) */ passes(val: number): DecrossTwoLayer<Ops>; /** * get the current number of passes */ passes(): number; /** @internal flag indicating that this is built in to d3dag and shouldn't error in specific instances */ readonly d3dagBuiltin: true; } /** default two layer operator */ export type DefaultDecrossTwoLayer = DecrossTwoLayer<{ /** default order */ order: TwolayerGreedy<TwolayerAgg>; /** default inits, both dfs based */ inits: readonly [DecrossDfs, DecrossDfs]; }>; /** * create a default {@link DecrossTwoLayer} * * This operator scans over the layered representation multiple times, applying * a heuristic to minimize the number of crossings between two layers. This * makes it much faster than complete methods, and produces a reasonable layout * in most cases, but there are some simply edge crossings that it won't * remove. * * It can be altered by setting both the heuristic it uses to * {@link DecrossTwoLayer#order} the nodes in a single layer to minimize edge * crossings, as well as the different {@link DecrossTwoLayer#inits} before * applying the two-layer heuristic. You can also tweak how many * {@link DecrossTwoLayer#passes} it runs. More can produce a better layout, * but may take longer. * * @example * * ```ts * const layout = sugiyama().decross(decrossTwoLayer()); * ``` */ export declare function decrossTwoLayer(...args: never[]): DefaultDecrossTwoLayer;