diff --git a/types/d3-hierarchy/d3-hierarchy-tests.ts b/types/d3-hierarchy/d3-hierarchy-tests.ts index 65b1f5c392..b75b9fbbd0 100644 --- a/types/d3-hierarchy/d3-hierarchy-tests.ts +++ b/types/d3-hierarchy/d3-hierarchy-tests.ts @@ -189,6 +189,10 @@ stratificatorizer = d3Hierarchy.stratify(); // id(...) +stratificatorizer = stratificatorizer.id((d) => { + return d.name; // d is of type TabularHierarchyDatum +}); + stratificatorizer = stratificatorizer.id((d, i, data) => { console.log('Length of tabular array: ', data.length); console.log('Name of first entry in tabular array: ', data[0].name); // data of type Array @@ -199,6 +203,10 @@ idStringAccessor = stratificatorizer.id(); // parentId(...) +stratificatorizer = stratificatorizer.parentId((d) => { + return d.parentId; // d is of type TabularHierarchyDatum +}); + stratificatorizer = stratificatorizer.parentId((d, i, data) => { console.log('Length of tabular array: ', data.length); console.log('Name of first entry in tabular array: ', data[0].name); // data of type Array @@ -225,14 +233,12 @@ clusterLayout = d3Hierarchy.cluster(); // size() ---------------------------------------------------------------- -clusterLayout = clusterLayout.size(null); clusterLayout = clusterLayout.size([200, 200]); size = clusterLayout.size(); // nodeSize() ------------------------------------------------------------ -clusterLayout = clusterLayout.nodeSize(null); clusterLayout = clusterLayout.nodeSize([10, 10]); size = clusterLayout.nodeSize(); @@ -358,14 +364,12 @@ treeLayout = d3Hierarchy.tree(); // size() ---------------------------------------------------------------- -treeLayout = treeLayout.size(null); treeLayout = treeLayout.size([200, 200]); size = treeLayout.size(); // nodeSize() ------------------------------------------------------------ -treeLayout = treeLayout.nodeSize(null); treeLayout = treeLayout.nodeSize([10, 10]); size = treeLayout.nodeSize(); @@ -416,7 +420,6 @@ tilingFn = treemapLayout.tile(); // size() ---------------------------------------------------------------- -treemapLayout = treemapLayout.size(null); treemapLayout = treemapLayout.size([400, 200]); size = treemapLayout.size(); @@ -635,7 +638,6 @@ partitionLayout = d3Hierarchy.partition(); // size() ---------------------------------------------------------------- -partitionLayout = partitionLayout.size(null); partitionLayout = partitionLayout.size([400, 200]); size = partitionLayout.size(); @@ -674,7 +676,6 @@ packLayout = d3Hierarchy.pack(); // size() ---------------------------------------------------------------- -packLayout = packLayout.size(null); packLayout = packLayout.size([400, 400]); size = packLayout.size(); diff --git a/types/d3-hierarchy/index.d.ts b/types/d3-hierarchy/index.d.ts index 440a779217..bdb7b652d5 100644 --- a/types/d3-hierarchy/index.d.ts +++ b/types/d3-hierarchy/index.d.ts @@ -1,65 +1,208 @@ // Type definitions for D3JS d3-hierarchy module 1.1 // Project: https://github.com/d3/d3-hierarchy/ -// Definitions by: Tom Wanzek , Alex Ford , Boris Yankov +// Definitions by: Tom Wanzek +// Alex Ford +// Boris Yankov +// denisname // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// Last module patch version validated against: 1.1.1 +// Last module patch version validated against: 1.1.6 // ----------------------------------------------------------------------- // Hierarchy // ----------------------------------------------------------------------- export interface HierarchyLink { + /** + * The source of the link. + */ source: HierarchyNode; + + /** + * The target of the link. + */ target: HierarchyNode; } export interface HierarchyNode { - data: Datum; - readonly depth: number; - readonly height: number; - parent: HierarchyNode | null; - children?: Array>; /** - * Aggregated numeric value as calculated by sum(value) or count(), - * if previously invoked. + * The associated data, as specified to the constructor. + */ + data: Datum; + + /** + * Zero for the root node, and increasing by one for each descendant generation. + */ + readonly depth: number; + + /** + * Zero for leaf nodes, and the greatest distance from any descendant leaf for internal nodes. + */ + readonly height: number; + + /** + * The parent node, or null for the root node. + */ + parent: this | null; + + /** + * An array of child nodes, if any; undefined for leaf nodes. + */ + children?: this[]; + + /** + * Aggregated numeric value as calculated by `sum(value)` or `count()`, if previously invoked. */ readonly value?: number; + /** - * Optional Node Id string set by StratifyOperator, if - * hierarchical data was created from tabular data using stratify() + * Optional node id string set by `StratifyOperator`, if hierarchical data was created from tabular data using stratify(). */ readonly id?: string; - ancestors(): Array>; - descendants(): Array>; - leaves(): Array>; - path(target: HierarchyNode): Array>; + + /** + * Returns the array of ancestors nodes, starting with this node, then followed by each parent up to the root. + */ + ancestors(): this[]; + + /** + * Returns the array of descendant nodes, starting with this node, then followed by each child in topological order. + */ + descendants(): this[]; + + /** + * Returns the array of leaf nodes in traversal order; leaves are nodes with no children. + */ + leaves(): this[]; + + /** + * Returns the shortest path through the hierarchy from this node to the specified target node. + * The path starts at this node, ascends to the least common ancestor of this node and the target node, and then descends to the target node. + * + * @param target The target node. + */ + path(target: this): this[]; + + /** + * Returns an array of links for this node, where each link is an object that defines source and target properties. + * The source of each link is the parent node, and the target is a child node. + */ links(): Array>; + + /** + * Evaluates the specified value function for this node and each descendant in post-order traversal, and returns this node. + * The `node.value` property of each node is set to the numeric value returned by the specified function plus the combined value of all descendants. + * + * @param value The value function is passed the node’s data, and must return a non-negative number. + */ sum(value: (d: Datum) => number): this; + + /** + * Computes the number of leaves under this node and assigns it to `node.value`, and similarly for every descendant of node. + * If this node is a leaf, its count is one. Returns this node. + */ count(): this; - sort(compare: (a: HierarchyNode, b: HierarchyNode) => number): this; - each(func: (node: HierarchyNode) => void): this; - eachAfter(func: (node: HierarchyNode) => void): this; - eachBefore(func: (node: HierarchyNode) => void): this; - copy(): HierarchyNode; + + /** + * Sorts the children of this node, if any, and each of this node’s descendants’ children, + * in pre-order traversal using the specified compare function, and returns this node. + * + * @param compare The compare function is passed two nodes a and b to compare. + * If a should be before b, the function must return a value less than zero; + * if b should be before a, the function must return a value greater than zero; + * otherwise, the relative order of a and b are not specified. See `array.sort` for more. + */ + sort(compare: (a: this, b: this) => number): this; + + /** + * Invokes the specified function for node and each descendant in breadth-first order, + * such that a given node is only visited if all nodes of lesser depth have already been visited, + * as well as all preceding nodes of the same depth. + * + * @param func The specified function is passed the current node. + */ + each(func: (node: this) => void): this; + + /** + * Invokes the specified function for node and each descendant in post-order traversal, + * such that a given node is only visited after all of its descendants have already been visited. + * + * @param func The specified function is passed the current node. + */ + eachAfter(func: (node: this) => void): this; + + /** + * Invokes the specified function for node and each descendant in pre-order traversal, + * such that a given node is only visited after all of its ancestors have already been visited. + * + * @param func The specified function is passed the current node. + */ + eachBefore(func: (node: this) => void): this; + + /** + * Return a deep copy of the subtree starting at this node. The returned deep copy shares the same data, however. + * The returned node is the root of a new tree; the returned node’s parent is always null and its depth is always zero. + */ + copy(): this; } +/** + * Constructs a root node from the specified hierarchical data. + * + * @param data The root specified data. + * @param children The specified children accessor function invoked for each datum, starting with the root data. + * Must return an array of data representing the children, and return null or undefined if the current datum has no children. + * If children is not specified, it defaults to: `(d) => d.children`. + */ export function hierarchy(data: Datum, children?: (d: Datum) => (Datum[] | null)): HierarchyNode; // ----------------------------------------------------------------------- // Stratify // ----------------------------------------------------------------------- -// TODO: Review the comment in the API documentation related to 'reserved properties': id, parentId, children. If this is referring to the element on node, it should be 'parent'? - export interface StratifyOperator { + /** + * Generates a new hierarchy from the specified tabular data. Each node in the returned object has a shallow copy of the properties + * from the corresponding data object, excluding the following reserved properties: id, parentId, children. + * + * @param data The root specified data. + * @throws Error on missing id, ambiguous id, cycle, multiple roots or no root. + */ (data: Datum[]): HierarchyNode; + + /** + * Returns the current id accessor, which defaults to: `(d) => d.id`. + */ id(): (d: Datum, i: number, data: Datum[]) => (string | null | '' | undefined); + /** + * Sets the id accessor to the given function. + * The id accessor is invoked for each element in the input data passed to the stratify operator. + * The returned string is then used to identify the node's relationships in conjunction with the parent id. + * For leaf nodes, the id may be undefined, null or the empty string; otherwise, the id must be unique. + * + * @param id The id accessor. + */ id(id: (d: Datum, i?: number, data?: Datum[]) => (string | null | '' | undefined)): this; + + /** + * Returns the current parent id accessor, which defaults to: `(d) => d.parentId`. + */ parentId(): (d: Datum, i: number, data: Datum[]) => (string | null | '' | undefined); + /** + * Sets the parent id accessor to the given function. + * The parent id accessor is invoked for each element in the input data passed to the stratify operator. + * The returned string is then used to identify the node's relationships in conjunction with the id. + * For the root node, the parent id should be undefined, null or the empty string. + * There must be exactly one root node in the input data, and no circular relationships. + * + * @param parentId The parent id accessor. + */ parentId(parentId: (d: Datum, i?: number, data?: Datum[]) => (string | null | '' | undefined)): this; } +/** + * Constructs a new stratify operator with the default settings. + */ export function stratify(): StratifyOperator; // ----------------------------------------------------------------------- @@ -67,52 +210,86 @@ export function stratify(): StratifyOperator; // ----------------------------------------------------------------------- export interface HierarchyPointLink { + /** + * The source of the link. + */ source: HierarchyPointNode; + + /** + * The target of the link. + */ target: HierarchyPointNode; } -export interface HierarchyPointNode { +export interface HierarchyPointNode extends HierarchyNode { + /** + * The x-coordinate of the node. + */ x: number; + + /** + * The y-coordinate of the node. + */ y: number; - data: Datum; - readonly depth: number; - readonly height: number; - parent: HierarchyPointNode | null; - children?: Array>; + /** - * Aggregated numeric value as calculated by sum(value) or count(), - * if previously invoked. + * Returns an array of links for this node, where each link is an object that defines source and target properties. + * The source of each link is the parent node, and the target is a child node. */ - readonly value?: number; - /** - * Optional Node Id string set by StratifyOperator, if - * hierarchical data was created from tabular data using stratify() - */ - readonly id?: string; - ancestors(): Array>; - descendants(): Array>; - leaves(): Array>; - path(target: HierarchyPointNode): Array>; links(): Array>; - sum(value: (d: Datum) => number): this; - count(): this; - sort(compare: (a: HierarchyPointNode, b: HierarchyPointNode) => number): this; - each(func: (node: HierarchyPointNode) => void): this; - eachAfter(func: (node: HierarchyPointNode) => void): this; - eachBefore(func: (node: HierarchyPointNode) => void): this; - copy(): HierarchyPointNode; } export interface ClusterLayout { + /** + * Lays out the specified root hierarchy. + * You may want to call `root.sort` before passing the hierarchy to the cluster layout. + * + * @param root The specified root hierarchy. + */ (root: HierarchyNode): HierarchyPointNode; + + /** + * Returns the current layout size, which defaults to [1, 1]. A layout size of null indicates that a node size will be used instead. + */ size(): [number, number] | null; + /** + * Sets this cluster layout’s size to the specified [width, height] array and returns the cluster layout. + * The size represent an arbitrary coordinate system; for example, to produce a radial layout, + * a size of [360, radius] corresponds to a breadth of 360° and a depth of radius. + * + * @param size The specified two-element size array. + */ size(size: [number, number]): this; + + /** + * Returns the current node size, which defaults to null. A node size of null indicates that a layout size will be used instead. + */ nodeSize(): [number, number] | null; + /** + * Sets this cluster layout’s node size to the specified [width, height] array and returns this cluster layout. + * When a node size is specified, the root node is always positioned at <0, 0>. + * + * @param size The specified two-element size array. + */ nodeSize(size: [number, number]): this; + + /** + * Returns the current separation accessor, which defaults to: `(a, b) => a.parent == b.parent ? 1 : 2`. + */ separation(): (a: HierarchyPointNode, b: HierarchyPointNode) => number; + /** + * Sets the separation accessor to the specified function and returns this cluster layout. + * The separation accessor is used to separate neighboring leaves. + * + * @param separation The separation function is passed two leaves a and b, and must return the desired separation. + * The nodes are typically siblings, though the nodes may be more distantly related if the layout decides to place such nodes adjacent. + */ separation(separation: (a: HierarchyPointNode, b: HierarchyPointNode) => number): this; } +/** + * Creates a new cluster layout with default settings. + */ export function cluster(): ClusterLayout; // ----------------------------------------------------------------------- @@ -120,15 +297,56 @@ export function cluster(): ClusterLayout; // ----------------------------------------------------------------------- export interface TreeLayout { + /** + * Lays out the specified root hierarchy. + * You may want to call `root.sort` before passing the hierarchy to the tree layout. + * + * @param root The specified root hierarchy. + */ (root: HierarchyNode): HierarchyPointNode; + + /** + * Returns the current layout size, which defaults to [1, 1]. A layout size of null indicates that a node size will be used instead. + */ size(): [number, number] | null; + /** + * Sets this tree layout’s size to the specified [width, height] array and returns the tree layout. + * The size represent an arbitrary coordinate system; for example, to produce a radial layout, + * a size of [360, radius] corresponds to a breadth of 360° and a depth of radius. + * + * @param size The specified two-element size array. + */ size(size: [number, number]): this; + + /** + * Returns the current node size, which defaults to null. A node size of null indicates that a layout size will be used instead. + */ nodeSize(): [number, number] | null; + /** + * Sets this tree layout’s node size to the specified [width, height] array and returns this tree layout. + * When a node size is specified, the root node is always positioned at <0, 0>. + * + * @param size The specified two-element size array. + */ nodeSize(size: [number, number]): this; + + /** + * Returns the current separation accessor, which defaults to: `(a, b) => a.parent == b.parent ? 1 : 2`. + */ separation(): (a: HierarchyPointNode, b: HierarchyPointNode) => number; + /** + * Sets the separation accessor to the specified function and returns this tree layout. + * The separation accessor is used to separate neighboring nodes. + * + * @param separation The separation function is passed two nodes a and b, and must return the desired separation. + * The nodes are typically siblings, though the nodes may be more distantly related if the layout decides to place such nodes adjacent. + */ separation(separation: (a: HierarchyPointNode, b: HierarchyPointNode) => number): this; } +/** + * Creates a new tree layout with default settings. + */ export function tree(): TreeLayout; // ----------------------------------------------------------------------- @@ -136,91 +354,283 @@ export function tree(): TreeLayout; // ----------------------------------------------------------------------- export interface HierarchyRectangularLink { + /** + * The source of the link. + */ source: HierarchyRectangularNode; + + /** + * The target of the link. + */ target: HierarchyRectangularNode; } -export interface HierarchyRectangularNode { +export interface HierarchyRectangularNode extends HierarchyNode { + /** + * The left edge of the rectangle. + */ x0: number; + + /** + * The top edge of the rectangle + */ y0: number; + + /** + * The right edge of the rectangle. + */ x1: number; + + /** + * The bottom edge of the rectangle. + */ y1: number; - data: Datum; - readonly depth: number; - readonly height: number; - parent: HierarchyRectangularNode | null; - children?: Array>; + /** - * Aggregated numeric value as calculated by sum(value) or count(), - * if previously invoked. + * Returns an array of links for this node, where each link is an object that defines source and target properties. + * The source of each link is the parent node, and the target is a child node. */ - readonly value?: number; - /** - * Optional Node Id string set by StratifyOperator, if - * hierarchical data was created from tabular data using stratify() - */ - readonly id?: string; - ancestors(): Array>; - descendants(): Array>; - leaves(): Array>; - path(target: HierarchyRectangularNode): Array>; links(): Array>; - sum(value: (d: Datum) => number): this; - count(): this; - sort(compare: (a: HierarchyRectangularNode, b: HierarchyRectangularNode) => number): this; - each(func: (node: HierarchyRectangularNode) => void): this; - eachAfter(func: (node: HierarchyRectangularNode) => void): this; - eachBefore(func: (node: HierarchyRectangularNode) => void): this; - copy(): HierarchyRectangularNode; } export interface TreemapLayout { + /** + * Lays out the specified root hierarchy. + * You must call `root.sum` before passing the hierarchy to the treemap layout. + * You probably also want to call `root.sort` to order the hierarchy before computing the layout. + * + * @param root The specified root hierarchy. + */ (root: HierarchyNode): HierarchyRectangularNode; + + /** + * Returns the current tiling method, which defaults to `d3.treemapSquarify` with the golden ratio. + */ tile(): (node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number) => void; + /** + * Sets the tiling method to the specified function and returns this treemap layout. + * + * @param tile The specified tiling function. + */ tile(tile: (node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number) => void): this; + + /** + * Returns the current size, which defaults to [1, 1]. + */ size(): [number, number]; + /** + * Sets this treemap layout’s size to the specified [width, height] array and returns this treemap layout. + * + * @param size The specified two-element size array. + */ size(size: [number, number]): this; + + /** + * Returns the current rounding state, which defaults to false. + */ round(): boolean; + /** + * Enables or disables rounding according to the given boolean and returns this treemap layout. + * + * @param round The specified boolean flag. + */ round(round: boolean): this; + + /** + * Returns the current inner padding function. + */ padding(): (node: HierarchyRectangularNode) => number; + /** + * Sets the inner and outer padding to the specified number and returns this treemap layout. + * + * @param padding The specified padding value. + */ padding(padding: number): this; + /** + * Sets the inner and outer padding to the specified function and returns this treemap layout. + * + * @param padding The specified padding function. + */ padding(padding: (node: HierarchyRectangularNode) => number): this; + + /** + * Returns the current inner padding function, which defaults to the constant zero. + */ paddingInner(): (node: HierarchyRectangularNode) => number; + /** + * Sets the inner padding to the specified number and returns this treemap layout. + * The inner padding is used to separate a node’s adjacent children. + * + * @param padding The specified inner padding value. + */ paddingInner(padding: number): this; + /** + * Sets the inner padding to the specified function and returns this treemap layout. + * The function is invoked for each node with children, being passed the current node. + * The inner padding is used to separate a node’s adjacent children. + * + * @param padding The specified inner padding function. + */ paddingInner(padding: (node: HierarchyRectangularNode) => number): this; + + /** + * Returns the current top padding function. + */ paddingOuter(): (node: HierarchyRectangularNode) => number; + /** + * Sets the top, right, bottom and left padding to the specified function and returns this treemap layout. + * + * @param padding The specified padding outer value. + */ paddingOuter(padding: number): this; + /** + * Sets the top, right, bottom and left padding to the specified function and returns this treemap layout. + * + * @param padding The specified padding outer function. + */ paddingOuter(padding: (node: HierarchyRectangularNode) => number): this; + + /** + * Returns the current top padding function, which defaults to the constant zero. + */ paddingTop(): (node: HierarchyRectangularNode) => number; + /** + * Sets the top padding to the specified number and returns this treemap layout. + * The top padding is used to separate the top edge of a node from its children. + * + * @param padding The specified top padding value. + */ paddingTop(padding: number): this; + /** + * Sets the top padding to the specified function and returns this treemap layout. + * The function is invoked for each node with children, being passed the current node. + * The top padding is used to separate the top edge of a node from its children. + * + * @param padding The specified top padding function. + */ paddingTop(padding: (node: HierarchyRectangularNode) => number): this; + + /** + * Returns the current right padding function, which defaults to the constant zero. + */ paddingRight(): (node: HierarchyRectangularNode) => number; + /** + * Sets the right padding to the specified number and returns this treemap layout. + * The right padding is used to separate the right edge of a node from its children. + * + * @param padding The specified right padding value. + */ paddingRight(padding: number): this; + /** + * Sets the right padding to the specified function and returns this treemap layout. + * The function is invoked for each node with children, being passed the current node. + * The right padding is used to separate the right edge of a node from its children. + * + * @param padding The specified right padding function. + */ paddingRight(padding: (node: HierarchyRectangularNode) => number): this; + + /** + * Returns the current bottom padding function, which defaults to the constant zero. + */ paddingBottom(): (node: HierarchyRectangularNode) => number; + /** + * Sets the bottom padding to the specified number and returns this treemap layout. + * The bottom padding is used to separate the bottom edge of a node from its children. + * + * @param padding The specified bottom padding value. + */ paddingBottom(padding: number): this; + /** + * Sets the bottom padding to the specified function and returns this treemap layout. + * The function is invoked for each node with children, being passed the current node. + * The bottom padding is used to separate the bottom edge of a node from its children. + * + * @param padding The specified bottom padding function. + */ paddingBottom(padding: (node: HierarchyRectangularNode) => number): this; + + /** + * Returns the current left padding function, which defaults to the constant zero. + */ paddingLeft(): (node: HierarchyRectangularNode) => number; + /** + * Sets the left padding to the specified number and returns this treemap layout. + * The left padding is used to separate the left edge of a node from its children. + * + * @param padding The specified left padding value. + */ paddingLeft(padding: number): this; + /** + * Sets the left padding to the specified function and returns this treemap layout. + * The function is invoked for each node with children, being passed the current node. + * The left padding is used to separate the left edge of a node from its children. + * + * @param padding The specified left padding function. + */ paddingLeft(padding: (node: HierarchyRectangularNode) => number): this; } +/** + * Creates a new treemap layout with default settings. + */ export function treemap(): TreemapLayout; -// Tiling functions --------------------------------------------------------------------------------- +// Tiling functions ----------------------------------------------------------------------- +/** + * Recursively partitions the specified nodes into an approximately-balanced binary tree, + * choosing horizontal partitioning for wide rectangles and vertical partitioning for tall rectangles. + */ export function treemapBinary(node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number): void; + +/** + * Divides the rectangular area specified by x0, y0, x1, y1 horizontally according the value of each of the specified node’s children. + * The children are positioned in order, starting with the left edge (x0) of the given rectangle. + * If the sum of the children’s values is less than the specified node’s value (i.e., if the specified node has a non-zero internal value), + * the remaining empty space will be positioned on the right edge (x1) of the given rectangle. + */ export function treemapDice(node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number): void; + +/** + * Divides the rectangular area specified by x0, y0, x1, y1 vertically according the value of each of the specified node’s children. + * The children are positioned in order, starting with the top edge (y0) of the given rectangle. + * If the sum of the children’s values is less than the specified node’s value (i.e., if the specified node has a non-zero internal value), + * the remaining empty space will be positioned on the bottom edge (y1) of the given rectangle. + */ export function treemapSlice(node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number): void; + +/** + * If the specified node has odd depth, delegates to treemapSlice; otherwise delegates to treemapDice. + */ export function treemapSliceDice(node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number): void; // TODO: Test Factory code export interface RatioSquarifyTilingFactory { (node: HierarchyRectangularNode, x0: number, y0: number, x1: number, y1: number): void; + + /** + * Specifies the desired aspect ratio of the generated rectangles. + * Note that the orientation of the generated rectangles (tall or wide) is not implied by the ratio. + * Furthermore, the rectangles ratio are not guaranteed to have the exact specified aspect ratio. + * If not specified, the aspect ratio defaults to the golden ratio, φ = (1 + sqrt(5)) / 2, per Kong et al. + * + * @param ratio The specified ratio value greater than or equal to one. + */ ratio(ratio: number): RatioSquarifyTilingFactory; } +/** + * Implements the squarified treemap algorithm by Bruls et al., which seeks to produce rectangles of a given aspect ratio. + */ export const treemapSquarify: RatioSquarifyTilingFactory; + +/** + * Like `d3.treemapSquarify`, except preserves the topology (node adjacencies) of the previous layout computed by `d3.treemapResquarify`, + * if there is one and it used the same target aspect ratio. This tiling method is good for animating changes to treemaps because + * it only changes node sizes and not their relative positions, thus avoiding distracting shuffling and occlusion. + * The downside of a stable update, however, is a suboptimal layout for subsequent updates: only the first layout uses the Bruls et al. squarified algorithm. + */ export const treemapResquarify: RatioSquarifyTilingFactory; // ----------------------------------------------------------------------- @@ -228,15 +638,53 @@ export const treemapResquarify: RatioSquarifyTilingFactory; // ----------------------------------------------------------------------- export interface PartitionLayout { + /** + * Lays out the specified root hierarchy. + * You must call `root.sum` before passing the hierarchy to the partition layout. + * You probably also want to call `root.sort` to order the hierarchy before computing the layout. + * + * @param root The specified root hierarchy. + */ (root: HierarchyNode): HierarchyRectangularNode; + + /** + * Returns the current size, which defaults to [1, 1]. + */ size(): [number, number]; + /** + * Sets this partition layout’s size to the specified [width, height] array and returns this partition layout. + * + * @param size The specified two-element size array. + */ size(size: [number, number]): this; + + /** + * Returns the current rounding state, which defaults to false. + */ round(): boolean; + /** + * Enables or disables rounding according to the given boolean and returns this partition layout. + * + * @param round The specified boolean flag. + */ round(round: boolean): this; + + /** + * Returns the current padding, which defaults to zero. + */ padding(): number; + /** + * Sets the padding to the specified number and returns this partition layout. + * The padding is used to separate a node’s adjacent children. + * + * @param padding The specified padding value. + */ padding(padding: number): this; } +/** + * Creates a new partition layout with the default settings. + */ export function partition(): PartitionLayout; // ----------------------------------------------------------------------- @@ -244,54 +692,110 @@ export function partition(): PartitionLayout; // ----------------------------------------------------------------------- export interface HierarchyCircularLink { + /** + * The source of the link. + */ source: HierarchyCircularNode; + + /** + * The target of the link. + */ target: HierarchyCircularNode; } -export interface HierarchyCircularNode { +export interface HierarchyCircularNode extends HierarchyNode { + /** + * The x-coordinate of the circle’s center. + */ x: number; + + /** + * The y-coordinate of the circle’s center. + */ y: number; + + /** + * The radius of the circle. + */ r: number; - data: Datum; - readonly depth: number; - readonly height: number; - parent: HierarchyCircularNode | null; - children?: Array>; + /** - * Aggregated numeric value as calculated by sum(value) or count(), - * if previously invoked. + * Returns an array of links for this node, where each link is an object that defines source and target properties. + * The source of each link is the parent node, and the target is a child node. */ - readonly value?: number; - /** - * Optional Node Id string set by StratifyOperator, if - * hierarchical data was created from tabular data using stratify() - */ - readonly id?: string; - ancestors(): Array>; - descendants(): Array>; - leaves(): Array>; - path(target: HierarchyCircularNode): Array>; links(): Array>; - sum(value: (d: Datum) => number): this; - count(): this; - sort(compare: (a: HierarchyCircularNode, b: HierarchyCircularNode) => number): this; - each(func: (node: HierarchyCircularNode) => void): this; - eachAfter(func: (node: HierarchyCircularNode) => void): this; - eachBefore(func: (node: HierarchyCircularNode) => void): this; - copy(): HierarchyCircularNode; } export interface PackLayout { + /** + * Lays out the specified root hierarchy. + * You must call `root.sum` before passing the hierarchy to the pack layout. + * You probably also want to call `root.sort` to order the hierarchy before computing the layout. + * + * @param root The specified root hierarchy. + */ (root: HierarchyNode): HierarchyCircularNode; + + /** + * Returns the current radius accessor, which defaults to null. + */ radius(): null | ((node: HierarchyCircularNode) => number); + /** + * Sets the pack layout’s radius accessor to the specified function and returns this pack layout. + * If the radius accessor is null, the radius of each leaf circle is derived from the leaf `node.value` (computed by `node.sum`); + * the radii are then scaled proportionally to fit the layout size. + * If the radius accessor is not null, the radius of each leaf circle is specified exactly by the function. + * + * @param radius The specified radius accessor. + */ radius(radius: (node: HierarchyCircularNode) => number): this; + + /** + * Returns the current size, which defaults to [1, 1]. + */ size(): [number, number]; + /** + * Sets this pack layout’s size to the specified [width, height] array and returns this pack layout. + * + * @param size The specified two-element size array. + */ size(size: [number, number]): this; + + /** + * Returns the current padding accessor, which defaults to the constant zero. + */ padding(): (node: HierarchyCircularNode) => number; + /** + * Sets this pack layout’s padding accessor to the specified number and returns this pack layout. + * Returns the current padding accessor, which defaults to the constant zero. + * + * When siblings are packed, tangent siblings will be separated by approximately the specified padding; + * the enclosing parent circle will also be separated from its children by approximately the specified padding. + * If an explicit radius is not specified, the padding is approximate because a two-pass algorithm + * is needed to fit within the layout size: the circles are first packed without padding; + * a scaling factor is computed and applied to the specified padding; and lastly the circles are re-packed with padding. + * + * @param padding The specified padding value. + */ padding(padding: number): this; + /** + * Sets this pack layout’s padding accessor to the specified function and returns this pack layout. + * Returns the current padding accessor, which defaults to the constant zero. + * + * When siblings are packed, tangent siblings will be separated by approximately the specified padding; + * the enclosing parent circle will also be separated from its children by approximately the specified padding. + * If an explicit radius is not specified, the padding is approximate because a two-pass algorithm + * is needed to fit within the layout size: the circles are first packed without padding; + * a scaling factor is computed and applied to the specified padding; and lastly the circles are re-packed with padding. + * + * @param padding The specified padding function. + */ padding(padding: (node: HierarchyCircularNode) => number): this; } +/** + * Creates a new pack layout with the default settings. + */ export function pack(): PackLayout; // ----------------------------------------------------------------------- @@ -299,8 +803,19 @@ export function pack(): PackLayout; // ----------------------------------------------------------------------- export interface PackCircle { + /** + * The radius of the circle. + */ r: number; + + /** + * The x-coordinate of the circle’s center. + */ x?: number; + + /** + * The y-coordinate of the circle’s center. + */ y?: number; } @@ -309,6 +824,19 @@ export interface PackCircle { // For invocation of packEnclose the x and y coordinates are mandatory. It seems easier to just comment // on the mandatory nature, then to create separate interfaces and having to deal with recasting. +/** + * Packs the specified array of circles, each of which must have a `circle.r` property specifying the circle’s radius. + * The circles are positioned according to the front-chain packing algorithm by Wang et al. + * + * @param circles The specified array of circles to pack. + */ export function packSiblings(circles: Datum[]): Datum[]; +/** + * Computes the smallest circle that encloses the specified array of circles, each of which must have + * a `circle.r` property specifying the circle’s radius, and `circle.x` and `circle.y` properties specifying the circle’s center. + * The enclosing circle is computed using the Matoušek-Sharir-Welzl algorithm. (See also Apollonius’ Problem.) + * + * @param circles The specified array of circles to pack. + */ export function packEnclose(circles: Datum[]): { r: number, x: number, y: number };