d3-dag
Version:
Layout algorithms for visualizing directed acylic graphs.
114 lines (113 loc) • 4.77 kB
TypeScript
/**
* 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;